unit kern_jit_asm; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface uses kern_thr, ucontext, x86_fpdbgdisas; {$DEFINE USE_XSAVE} { change: rsp,rbp,rip eflahs: temp change change: push/pop frame: r13 temp: r14,r15 } const jit_frame_offset:Integer=Integer(@kthread(nil^).td_frame)+Integer(@trapframe(nil^).tf_r13); type //kthread.td_frame.tf_r13 p_jit_frame=^jit_frame; jit_frame=packed record tf__00:QWORD; //00 (tf_r13) tf_r14:QWORD; //08 tf_r15:QWORD; //10 tf_r13:QWORD; //18 (tf_trapno) tf_adr:QWORD; //20 (tf_addr) tf__28:QWORD; //28 (tf_flags) tf_rsp:QWORD; //30 (tf_BrF) tf_rbp:QWORD; //38 (tf_BrT) tf_err:QWORD; //40 (tf_err) tf_rip:QWORD; //48 (tf_rip) end; p_jplt_cache_asm=^t_jplt_cache_asm; t_jplt_cache_asm=object plt:Pointer; src:Pointer; neg:Pointer; //(-src) dst:Pointer; end; procedure jit_syscall; assembler; procedure jit_jmp_plt_cache; assembler; procedure jit_jmp_dispatch; assembler; procedure jit_hle_trace; assembler; procedure jit_jmp_internal; assembler; function IS_JIT_FUNC(rip:qword):Boolean; procedure jit_save_ctx; procedure jit_load_ctx; procedure jit_save_to_sys_save(td:p_kthread); procedure sys_save_to_jit_save(td:p_kthread); procedure jit_cpuid; assembler; procedure strict_ps4_rdtsc_jit; assembler; procedure strict_ps4_rdtscp_jit; assembler; procedure jit_interrupt_nop; assembler; implementation uses time, md_time, trap, md_context, signal, sys_bootparam, subr_backtrace; // function jmp_dispatcher(addr,plt,from:Pointer):Pointer; external; // procedure jit_simple_save_ctx; assembler; nostackframe; asm movqq %rdi, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rdi(%r13) movqq %rsi, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rsi(%r13) movqq %rdx, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rdx(%r13) movqq %rcx, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rcx(%r13) movqq %r8 , - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r8 (%r13) movqq %r9 , - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r9 (%r13) movqq %rax, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rax(%r13) movqq %r10, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r10(%r13) movqq %r11, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r11(%r13) end; procedure jit_simple_load_ctx; assembler; nostackframe; asm movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rdi(%r13), %rdi movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rsi(%r13), %rsi movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rdx(%r13), %rdx movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rcx(%r13), %rcx movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r8 (%r13), %r8 movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r9 (%r13), %r9 movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rax(%r13), %rax movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r10(%r13), %r10 movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r11(%r13), %r11 end; // //in:tf_rip procedure jit_syscall; assembler; nostackframe; label _after_call, _doreti, _fail, _ast, _doreti_exit; asm //prolog (debugger) pushq %rbp movqq %rsp,%rbp andq $-16,%rsp //align stack pushf pop %r14 movqq %gs:teb.thread,%r15 //curkthread test %r15,%r15 jz _fail andl NOT_PCB_FULL_IRET,kthread.pcb_flags(%r15) //clear PCB_FULL_IRET movqq %r14,kthread.td_frame.tf_rflags(%r15) //save flags movqq %rdi,kthread.td_frame.tf_rdi(%r15) movqq %rsi,kthread.td_frame.tf_rsi(%r15) movqq %rdx,kthread.td_frame.tf_rdx(%r15) movqq $0,kthread.td_frame.tf_rcx(%r15) movqq %r8 ,kthread.td_frame.tf_r8 (%r15) movqq %r9 ,kthread.td_frame.tf_r9 (%r15) movqq %rax,kthread.td_frame.tf_rax(%r15) movqq %rbx,kthread.td_frame.tf_rbx(%r15) movqq %r10,kthread.td_frame.tf_r10(%r15) movqq $0,kthread.td_frame.tf_r11(%r15) movqq %r12,kthread.td_frame.tf_r12(%r15) //tf_r14=tf_r14 //tf_r15=tf_r15 //tf_r13 movqq jit_frame.tf_r13(%r13),%r14 movqq %r14,kthread.td_frame.tf_r13(%r15) //tf_rsp movqq jit_frame.tf_rsp(%r13),%r14 movqq %r14,kthread.td_frame.tf_rsp(%r15) //tf_rbp movqq jit_frame.tf_rbp(%r13),%r14 movqq %r14,kthread.td_frame.tf_rbp(%r15) movqq $1,kthread.td_frame.tf_trapno(%r15) movqq $0,kthread.td_frame.tf_addr (%r15) movqq $0,kthread.td_frame.tf_flags (%r15) movqq $2,kthread.td_frame.tf_err (%r15) //sizeof(syscall) call amd64_syscall _after_call: movq %gs:teb.thread ,%r15 //curkthread leaq kthread.td_frame.tf_r13(%r15),%r13 //jit_frame //Requested full context restore testl PCB_FULL_IRET,kthread.pcb_flags(%r15) jnz _doreti testl TDF_AST,kthread.td_flags(%r15) jne _ast //Restore preserved registers. //get flags movqq kthread.td_frame.tf_rflags(%r15),%r14 push %r14 popf movqq kthread.td_frame.tf_rdi(%r15),%rdi movqq kthread.td_frame.tf_rsi(%r15),%rsi movqq kthread.td_frame.tf_rdx(%r15),%rdx movqq kthread.td_frame.tf_rax(%r15),%rax //tf_r14=tf_r14 //tf_r15=tf_r15 //tf_r13 movqq kthread.td_frame.tf_r13(%r15),%r14 movqq %r14,jit_frame.tf_r13(%r13) //tf_rsp movqq kthread.td_frame.tf_rsp(%r15),%r14 movqq %r14,jit_frame.tf_rsp(%r13) //tf_rbp movqq kthread.td_frame.tf_rbp(%r15),%r14 movqq %r14,jit_frame.tf_rbp(%r13) movqq $0,%rcx movqq $0,%r11 //epilog (debugger) movq %rbp,%rsp popq %rbp ret //fail (curkthread=nil) _fail: or $1,%r14 //set CF push %r14 popf movqq $14,%rax //EFAULT movqq $0,%rdx movqq $0,%rcx movqq $0,%r11 //epilog (debugger) movq %rbp,%rsp popq %rbp ret //ast _ast: call ast jmp _after_call //doreti _doreti: //%r15=curkthread testl TDF_AST,kthread.td_flags(%r15) je _doreti_exit call ast jmp _doreti _doreti_exit: //Restore full. call ipi_sigreturn hlt //marker .quad 0xDEADC0DEDEADC0DE end; procedure jit_save_to_sys_save(td:p_kthread); public; var frame:p_jit_frame; begin frame:=@td^.td_frame.tf_r13; //tf_rip ????? td^.td_frame.tf_r13:=frame^.tf_r13; td^.td_frame.tf_rsp:=frame^.tf_rsp; td^.td_frame.tf_rbp:=frame^.tf_rbp; td^.td_frame.tf_trapno:=0; td^.td_frame.tf_BrF :=0; td^.td_frame.tf_BrT :=0; end; procedure sys_save_to_jit_save(td:p_kthread); public; var frame:p_jit_frame; begin frame:=@td^.td_frame.tf_r13; frame^.tf_r13:=td^.td_frame.tf_r13; frame^.tf_rsp:=td^.td_frame.tf_rsp; frame^.tf_rbp:=td^.td_frame.tf_rbp; end; procedure jit_save_ctx; assembler; nostackframe; asm movqq %rdi, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rdi(%r13) movqq %rsi, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rsi(%r13) movqq %rdx, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rdx(%r13) movqq %rcx, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rcx(%r13) movqq %r8 , - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r8 (%r13) movqq %r9 , - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r9 (%r13) movqq %rbx, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rbx(%r13) movqq %rax, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rax(%r13) movqq %r10, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r10(%r13) movqq %r11, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r11(%r13) movqq %r12, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r12(%r13) //tf_r14=tf_r14 //tf_r15=tf_r15 { //tf_r13 movqq jit_frame.tf_r13(%r13),%rdi movqq %rdi, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r13(%r13) //tf_rsp movqq jit_frame.tf_rsp(%r13),%rdi movqq %rdi, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rsp(%r13) //tf_rbp movqq jit_frame.tf_rbp(%r13),%rdi movqq %rdi, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rbp(%r13) } //tf_rflags pushf pop %rdi movqq %rdi, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rflags(%r13); lea - kthread.td_frame.tf_r13 + kthread.td_fpstate(%r13), %rdi //and $-32,%rdi {$IFDEF USE_XSAVE} movqq $0,t_fpstate.XSTATE_BV(%rdi) movqq $0,t_fpstate.XCOMP_BV (%rdi) mov $7,%eax xor %edx,%edx //xsave64 (%rdi) //480FAE27 .byte 0x48, 0x0F, 0xAE, 0x27 // {$ELSE} vmovdqa %ymm0 ,0x000(%rdi) vmovdqa %ymm1 ,0x020(%rdi) vmovdqa %ymm2 ,0x040(%rdi) vmovdqa %ymm3 ,0x060(%rdi) vmovdqa %ymm4 ,0x080(%rdi) vmovdqa %ymm5 ,0x0A0(%rdi) vmovdqa %ymm6 ,0x0C0(%rdi) vmovdqa %ymm7 ,0x0E0(%rdi) vmovdqa %ymm8 ,0x100(%rdi) vmovdqa %ymm9 ,0x120(%rdi) vmovdqa %ymm10,0x140(%rdi) vmovdqa %ymm11,0x160(%rdi) vmovdqa %ymm12,0x180(%rdi) vmovdqa %ymm13,0x1A0(%rdi) vmovdqa %ymm14,0x1C0(%rdi) vmovdqa %ymm15,0x1E0(%rdi) {$ENDIF} end; procedure jit_load_ctx; assembler; nostackframe; asm lea - kthread.td_frame.tf_r13 + kthread.td_fpstate(%r13), %rdi //and $-32,%rdi {$IFDEF USE_XSAVE} mov $7,%eax xor %edx,%edx and __INITIAL_MXCSR_MASK__, t_fpstate.XMM_SAVE_AREA.MxCsr_Mask(%rdi) //xrstor (%rdi) //0FAE2F .byte 0x0F, 0xAE, 0x2F // {$ELSE} vmovdqa 0x000(%rdi),%ymm0 vmovdqa 0x020(%rdi),%ymm1 vmovdqa 0x040(%rdi),%ymm2 vmovdqa 0x060(%rdi),%ymm3 vmovdqa 0x080(%rdi),%ymm4 vmovdqa 0x0A0(%rdi),%ymm5 vmovdqa 0x0C0(%rdi),%ymm6 vmovdqa 0x0E0(%rdi),%ymm7 vmovdqa 0x100(%rdi),%ymm8 vmovdqa 0x120(%rdi),%ymm9 vmovdqa 0x140(%rdi),%ymm10 vmovdqa 0x160(%rdi),%ymm11 vmovdqa 0x180(%rdi),%ymm12 vmovdqa 0x1A0(%rdi),%ymm13 vmovdqa 0x1C0(%rdi),%ymm14 vmovdqa 0x1E0(%rdi),%ymm15 {$ENDIF} { //tf_r13 movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r13(%r13),%rdi movqq %rdi,jit_frame.tf_r13(%r13) //tf_rsp movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rsp(%r13),%rdi movqq %rdi,jit_frame.tf_rsp(%r13) //tf_rbp movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rbp(%r13),%rdi movqq %rdi,jit_frame.tf_rbp(%r13) } //tf_rflags movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rflags(%r13), %rdi push %rdi popf movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rdi(%r13), %rdi movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rsi(%r13), %rsi movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rdx(%r13), %rdx movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rcx(%r13), %rcx movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r8 (%r13), %r8 movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r9 (%r13), %r9 movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rbx(%r13), %rbx movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rax(%r13), %rax movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r10(%r13), %r10 movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r11(%r13), %r11 movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_r12(%r13), %r12 //tf_r14=tf_r14 //tf_r15=tf_r15 end; //in:r14(addr) r15(plt) out:r14(addr) procedure jit_jmp_plt_cache; assembler; nostackframe; label _exit; asm //load cache pushf push %rbp movq (%r15),%rbp //plt^ cmpq t_jplt_cache_asm.src(%rbp),%r14 jne _exit //get blk //movq t_jplt_cache_asm.blk(%rbp),%r14 //save current block //movqq %r14, - kthread.td_frame.tf_r13 + kthread.td_jctx.block(%r13) //get dst movq t_jplt_cache_asm.dst(%rbp),%r14 pop %rbp popf //restore rbp //movq %rsp,%rbp //leaq 8(%rbp),%rbp //interrupt jmp %gs:teb.jit_trp //ret _exit: pop %rbp popf //restore rbp //movq %rsp,%rbp //leaq 8(%rbp),%rbp jmp jit_jmp_dispatch //marker .quad 0xDEADC0DEDEADC0DE end; //in:r14(addr) r15(plt) out:r14(addr) procedure jit_jmp_dispatch; assembler; nostackframe; asm //prolog (debugger) push %rbp movq %rsp,%rbp movq %gs:teb.thread,%r13 //curkthread leaq kthread.td_frame.tf_r13(%r13),%r13 //jit_frame call jit_save_ctx // -> pushf andq $-16,%rsp //align stack //rdi,rsi,rdx mov %r14,%rdi mov %r15,%rsi mov 8(%rbp),%rdx call jmp_dispatcher mov %rax,%r14 call jit_load_ctx // -> popf //epilog movq %rbp,%rsp pop %rbp //interrupt jmp %gs:teb.jit_trp //marker .quad 0xDEADC0DEDEADC0DE end; //in:r14(nid) r15(caller) procedure jit_hle_trace; assembler; nostackframe; asm //prolog (debugger) push %rbp movq %rsp,%rbp call jit_save_ctx // -> pushf andq $-16,%rsp //align stack //rdi mov %r14,%rdi call %r15 call jit_load_ctx // -> popf //epilog movq %rbp,%rsp pop %rbp //interrupt jmp %gs:teb.jit_trp //marker .quad 0xDEADC0DEDEADC0DE end; procedure stack_set_user; assembler; nostackframe; asm //switch stack movqq %rsp, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rsp(%r13) movqq %rbp, - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rbp(%r13) movq jit_frame.tf_rsp(%r13),%rsp movq jit_frame.tf_rbp(%r13),%rbp //switch stack //teb movq - kthread.td_frame.tf_r13 + kthread.td_kstack.sttop(%r13) ,%r14 movq - kthread.td_frame.tf_r13 + kthread.td_kstack.stack(%r13) ,%r15 movq %r14,%gs:teb.sttop movq %r15,%gs:teb.stack //teb end; procedure stack_set_jit; assembler; nostackframe; asm //switch stack movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rsp(%r13), %rsp movqq - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rbp(%r13), %rbp //switch stack //teb movq - kthread.td_frame.tf_r13 + kthread.td_ustack.sttop(%r13) ,%r14 movq - kthread.td_frame.tf_r13 + kthread.td_ustack.stack(%r13) ,%r15 movq %r14,%gs:teb.sttop movq %r15,%gs:teb.stack //teb //uplift %rsp/%rbp ??? end; procedure jit_jmp_internal; assembler; nostackframe; asm //prolog (debugger) push %rbp movq %rsp,%rbp //call stack_set_user //movqq jit_frame.tf_r14(%r13),%r14 //movqq jit_frame.tf_r15(%r13),%r15 //movqq jit_frame.tf_r13(%r13),%r13 call %gs:teb.jitcall //restore guard movq %gs:teb.thread ,%r13 //curkthread leaq kthread.td_frame.tf_r13(%r13),%r13 //jit_frame //call stack_set_jit //epilog pop %rbp //pop host call mov jit_frame.tf_rsp(%r13),%r14 //uplift_jit //get addr mov (%r14),%r14 //lea rsp,[rsp+8] mov jit_frame.tf_rsp(%r13),%r15 lea 8(%r15),%r15 mov %r15,jit_frame.tf_rsp(%r13) //set zero plt mov $0, %r15 jmp jit_jmp_dispatch end; procedure _jit_cpuid(tf_rip,rax:qword); var td:p_kthread; begin td:=curkthread; jit_save_to_sys_save(td); td^.td_frame.tf_rip:=tf_rip; print_error_td('TODO:jit_cpuid:0x'+HexStr(rax,8)); Assert(False); end; //cpuid(0x00000000,0x0):eax=0x0000000d ebx=0x68747541 ecx=0x444d4163 edx=0x69746e65 //cpuid(0x00000001,0x0):eax=0x00710f31 ebx=0x07080800 ecx=0x3ed8220b edx=0x178bfbff //cpuid(0x00000002,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000003,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000004,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000005,0x0):eax=0x00000040 ebx=0x00000040 ecx=0x00000003 edx=0x00000000 //cpuid(0x00000006,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000001 edx=0x00000000 //cpuid(0x00000007,0x0):eax=0x00000000 ebx=0x00000008 ecx=0x00000000 edx=0x00000000 //cpuid(0x00000007,0x1):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000007,0x2):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x0000000b,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x0000000d,0x0):eax=0x00000007 ebx=0x00000340 ecx=0x00000340 edx=0x00000000 //cpuid(0x00000012,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000014,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000014,0x1):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000015,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000016,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000017,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x00000019,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x0000001d,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x40000000,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x40000010,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x80000000,0x0):eax=0x8000001e ebx=0x68747541 ecx=0x444d4163 edx=0x69746e65 //cpuid(0x80000001,0x0):eax=0x00710f31 ebx=0x00000000 ecx=0x154837ff edx=0x2fd3fbff //cpuid(0x80000002,0x0):eax=0x31314744 ebx=0x4b533130 ecx=0x48343846 edx=0x20202056 //cpuid(0x80000003,0x0):eax=0x20202020 ebx=0x20202020 ecx=0x20202020 edx=0x20202020 //cpuid(0x80000004,0x0):eax=0x20202020 ebx=0x20202020 ecx=0x20202020 edx=0x00202020 //cpuid(0x80000005,0x0):eax=0xff08ff08 ebx=0xff28ff20 ecx=0x20080140 edx=0x20020140 //cpuid(0x80000006,0x0):eax=0x21000000 ebx=0x42004200 ecx=0x08008140 edx=0x00000000 //cpuid(0x80000007,0x0):eax=0x0d6b0101 ebx=0x00000001 ecx=0x00000000 edx=0x000009d9 //cpuid(0x80000008,0x0):eax=0x00003028 ebx=0x00000000 ecx=0x00003007 edx=0x00000000 //cpuid(0x8000000a,0x0):eax=0x00000001 ebx=0x00000008 ecx=0x00000000 edx=0x00001cdf //cpuid(0x8000001d,0x0):eax=0x00000121 ebx=0x01c0003f ecx=0x0000003f edx=0x00000000 //cpuid(0x8000001f,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x80000021,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0x8fffffff,0x0):eax=0x4c4c4548 ebx=0x494b204f ecx=0x21595454 edx=0x5e2d5e20 //cpuid(0xc0000000,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero //cpuid(0xc0000001,0x0):eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 //all zero procedure jit_cpuid; assembler; nostackframe; label _zero, _cpuid_0, _cpuid_1, _cpuid_5, _cpuid_6, _cpuid_7, _cpuid_80000000, _cpuid_80000001, _cpuid_80000002, _cpuid_80000003, _cpuid_80000005, _cpuid_80000006, _cpuid_80000007, _cpuid_80000008, _cpuid_8000000a, _cpuid_8000001d, _cpuid_8fffffff, _exit; asm movq %rax, %r14 seto %al lahf xchg %rax, %r14 cmp $0,%eax je _cpuid_0 cmp $1,%eax je _cpuid_1 cmp $5,%eax je _cpuid_5 cmp $6,%eax je _cpuid_6 cmp $7,%eax je _cpuid_7 cmp $0x80000000,%eax je _cpuid_80000000 cmp $0x80000001,%eax je _cpuid_80000001 cmp $0x80000002,%eax je _cpuid_80000002 cmp $0x80000003,%eax je _cpuid_80000003 cmp $0x80000004,%eax je _cpuid_80000003 cmp $0x80000005,%eax je _cpuid_80000005 cmp $0x80000006,%eax je _cpuid_80000006 cmp $0x80000007,%eax je _cpuid_80000007 cmp $0x80000008,%eax je _cpuid_80000008 cmp $0x8000000a,%eax je _cpuid_8000000a cmp $0x8000001d,%eax je _cpuid_8000001d cmp $0x8fffffff,%eax je _cpuid_8fffffff //unknow to zero -> { //unknow id xchg %r14, %rax addb $127, %al sahf mov %r14, %r15 call jit_save_ctx mov %r14, %rdi mov %r15, %rsi jmp _jit_cpuid //not reach } _zero: mov $0x0,%eax mov $0x0,%ebx mov $0x0,%edx mov $0x0,%ecx jmp _exit // _cpuid_0: //cpu_high mov $0xD,%eax //cpu_vendor mov $0x68747541,%ebx mov $0x69746E65,%edx mov $0x444D4163,%ecx jmp _exit // _cpuid_1: //get host cpuid //if ((cpu_id & 0xffffff80) == 0x740f00) then //if "machdep.bootparams.base_ps4_mode" then sceKernelHasNeoMode //if ((cpu_id & 0xffffff80) == 0x740f00) then sceKernelIsAuthenticNeo mov p_cpuid ,%eax //cpu_id mov $0x178bfbff,%edx //cpu_feature mov $0x3ed8220b,%ecx //cpu_feature2 // 0x07080800 //CPUID_BRAND_INDEX 0x000000ff //CPUID_CLFUSH_SIZE 0x0000ff00 //CPUID_HTT_CORES 0x00ff0000 //CPUID_LOCAL_APIC_ID 0xff000000 //sceKernelGetCurrentCpu 0..7 and $0x07000000,%ebx //filter CPUID_LOCAL_APIC_ID 0..7 or $0x00080800,%ebx //cpu_procinfo jmp _exit // _cpuid_5: mov $0x00000040,%eax mov $0x00000040,%ebx mov $0x00000000,%edx mov $0x00000003,%ecx jmp _exit _cpuid_6: mov $0x00000000,%eax mov $0x00000000,%ebx mov $0x00000000,%edx mov $0x00000001,%ecx jmp _exit _cpuid_7: test %ecx,%ecx //set bits if ecx=0 mov $0x0,%eax mov $0x0,%ebx mov $0x0,%edx mov $0x0,%ecx mov $0x8,%r15d cmove %r15d,%ebx //if ecx=0 {ebx=8} jmp _exit // _cpuid_80000000: //cpu_exthigh mov $0x8000001E,%eax //cpu_vendor mov $0x68747541,%ebx mov $0x69746e65,%edx mov $0x444d4163,%ecx jmp _exit // _cpuid_80000001: mov $0x00710f31,%eax mov $0x00000000,%ebx mov $0x2fd3fbff,%edx //amd_feature mov $0x154837ff,%ecx //amd_feature2 jmp _exit // _cpuid_80000002: mov $0x31314744,%eax mov $0x4b533130,%ebx mov $0x20202056,%edx mov $0x48343846,%ecx jmp _exit // _cpuid_80000003: mov $0x20202020,%eax mov $0x20202020,%ebx mov $0x20202020,%edx mov $0x20202020,%ecx jmp _exit // _cpuid_80000005: mov $0xff08ff08,%eax mov $0xff28ff20,%ebx mov $0x20020140,%edx mov $0x20080140,%ecx jmp _exit // _cpuid_80000006: mov $0x21000000,%eax mov $0x42004200,%ebx mov $0x00000000,%edx mov $0x08008140,%ecx jmp _exit // _cpuid_80000007: mov $0x0d6b0101,%eax mov $0x00000001,%ebx mov $0x000009d9,%edx mov $0x00000000,%ecx jmp _exit // _cpuid_80000008: mov $0x00003028,%eax mov $0x00000000,%ebx mov $0x00000000,%edx mov $0x00003007,%ecx //cpu_procinfo2 jmp _exit // _cpuid_8000000a: mov $0x00000001,%eax mov $0x00000008,%ebx mov $0x00001cdf,%edx mov $0x00000000,%ecx jmp _exit _cpuid_8000001d: mov $0x00000121,%eax mov $0x01c0003f,%ebx mov $0x00000000,%edx mov $0x0000003f,%ecx jmp _exit _cpuid_8fffffff: mov $0x4c4c4548,%eax mov $0x494b204f,%ebx mov $0x5e2d5e20,%edx mov $0x21595454,%ecx _exit: xchg %r14, %rax addb $127, %al sahf movq %r14, %rax //interrupt jmp %gs:teb.jit_trp end; procedure strict_ps4_rdtsc_jit; assembler; nostackframe; asm seto %al lahf movq %rax, %r14 // rdtsc // shl $32, %rdx or %rdx, %rax // mulq tsc_freq(%rip) divq md_tsc_freq(%rip) // mov %rax, %rdx shr $32, %rdx shl $32, %rax shr $32, %rax // xchg %r14, %rax addb $127, %al sahf movq %r14, %rax end; procedure strict_ps4_rdtscp_jit; assembler; nostackframe; asm // seto %al lahf movq %rax, %r15 // movq %rbx, %r14 // mov $1, %eax cpuid // shr $6, %ebx and $7, %ebx // mov $7 , %ecx sub %ebx, %ecx // mov %r14, %rbx // lfence rdtsc lfence // shl $32, %rdx or %rdx, %rax // mulq tsc_freq(%rip) divq md_tsc_freq(%rip) // mov %rax, %rdx shr $32, %rdx shl $32, %rax shr $32, %rax // xchg %r15, %rax addb $127, %al sahf movq %r15, %rax end; procedure jit_interrupt_nop; assembler; nostackframe; asm 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 jit_syscall_end :Pointer=nil; jit_jmp_dispatch_end :Pointer=nil; jit_jmp_plt_cache_end:Pointer=nil; function IS_JIT_FUNC(rip:qword):Boolean; public; begin if (jit_syscall_end =nil) then jit_syscall_end :=IndexMarker(@jit_syscall); if (jit_jmp_dispatch_end =nil) then jit_jmp_dispatch_end :=IndexMarker(@jit_jmp_dispatch); if (jit_jmp_plt_cache_end=nil) then jit_jmp_plt_cache_end:=IndexMarker(@jit_jmp_plt_cache); Result:=( (rip>=QWORD(@jit_syscall)) and (rip<=(QWORD(jit_syscall_end))) //jit_syscall func size ) or ( (rip>=QWORD(@jit_jmp_dispatch)) and (rip<=(QWORD(jit_jmp_dispatch_end))) //jit_jmp_dispatch func size ) or ( (rip>=QWORD(@jit_jmp_plt_cache)) and (rip<=(QWORD(jit_jmp_plt_cache_end))) //jit_jmp_plt_cache func size ); end; end.