diff --git a/chip/pm4defs.pas b/chip/pm4defs.pas index 38b5b82e..b4b8739d 100644 --- a/chip/pm4defs.pas +++ b/chip/pm4defs.pas @@ -319,6 +319,36 @@ type addressHi:bit16; // < base address Hi of buffer end; +const + SET_PRED_CLEAR =0; + SET_PRED_ZPASS =1; + SET_PRED_PRIMCOUNT=2; + SET_PRED_MEM =3; + +type + PPM4CMDSETPREDICATION=^PM4CMDSETPREDICATION; + PM4CMDSETPREDICATION=bitpacked record + header :PM4_TYPE_3_HEADER; + startAddressLo :bit32; // < start address low + startAddrHi :bit8; // < start address hi + predicationBoolean:bit1; // < predication boolean + reserved1 :bit3; + hint :bit1; // < hint + // < (only valid for Zpass/Occlusion Predicate) + reserved2 :bit3; + predOp :bit3; // < predicate operation + reserved3 :bit12; + continueBit :bit1; // < continue set predication + end; + + PPM4CMDDRAWPREAMBLE=^PM4CMDDRAWPREAMBLE; + PM4CMDDRAWPREAMBLE=bitpacked record + header :PM4_TYPE_3_HEADER; + control1 :TVGT_PRIMITIVE_TYPE; //< writes to VGT_PRIMITIVE_TYPE reg + control2 :TIA_MULTI_VGT_PARAM; //< writes to IA_MULTI_VGT_PARAM reg + control3 :TVGT_LS_HS_CONFIG; //< writes to VGT_LS_HS_CONFIG reg + end; + // WRITE_DATA DST_SEL and ENGINE definitions const WRITE_DATA_DST_SEL_REGISTER =0; diff --git a/gui/main.pas b/gui/main.pas index 17d941b9..63ae99e4 100644 --- a/gui/main.pas +++ b/gui/main.pas @@ -635,7 +635,7 @@ begin cfg.hOutput:=FAddHandle; cfg.hError :=FAddHandle; - cfg.fork_proc:=False; + cfg.fork_proc:=True; if Item.FLock then Exit; diff --git a/sys/dev/dev_gc.pas b/sys/dev/dev_gc.pas index ccd2d8f4..1892745d 100644 --- a/sys/dev/dev_gc.pas +++ b/sys/dev/dev_gc.pas @@ -165,22 +165,52 @@ begin end; +function revbinstr(val:int64;cnt:byte):shortstring; +var + i:Integer; +begin + Result[0]:=AnsiChar(cnt); + for i:=1 to cnt do + begin + Result[i]:=AnsiChar(48+val and 1); + val:=val shr 1; + end; +end; + procedure onContextControl(Body:PPM4CMDCONTEXTCONTROL); begin - Writeln(' loadControl =b',BinStr(DWORD(Body^.loadControl ),32)); - Writeln(' shadowEnable=b',BinStr(DWORD(Body^.shadowEnable),32)); + Writeln(' loadControl =b',revbinstr(DWORD(Body^.loadControl ),32)); + Writeln(' shadowEnable=b',revbinstr(DWORD(Body^.shadowEnable),32)); end; procedure onSetBase(Body:PPM4CMDDRAWSETBASE); var addr:QWORD; begin - addr:=Body^.addressLo or Body^.addressHi; + addr:=Body^.addressLo or (Body^.addressHi shl 32); Writeln(' baseIndex=0x',HexStr(Body^.baseIndex,4)); Writeln(' address =0x',HexStr(addr,16)); end; +procedure onSetPredication(Body:PPM4CMDSETPREDICATION); +var + addr:QWORD; +begin + addr:=Body^.startAddressLo or (Body^.startAddrHi shl 32); + + Writeln(' startAddress=0x',HexStr(addr,16)); + Writeln(' pred =',Body^.predicationBoolean); + Writeln(' hint =',Body^.hint); + Writeln(' predOp =',Body^.predOp); + Writeln(' continueBit =',Body^.continueBit); +end; + +procedure onDrawPreamble(Body:PPM4CMDDRAWPREAMBLE); +begin + //Writeln; +end; + procedure onSetShReg(Body:PPM4CMDSETDATA); begin Writeln(' 0x',HexStr(SH_REG_BASE+Body^.REG_OFFSET,4),'..', @@ -240,8 +270,8 @@ begin IT_PFP_SYNC_ME :; IT_SET_BASE :onSetBase(buff); - IT_DRAW_PREAMBLE :; - IT_SET_PREDICATION :; + IT_DRAW_PREAMBLE :onDrawPreamble(buff); + IT_SET_PREDICATION :onSetPredication(buff); else; end; diff --git a/sys/init_sysent.pas b/sys/init_sysent.pas index 29f495fb..41495af6 100644 --- a/sys/init_sysent.pas +++ b/sys/init_sysent.pas @@ -383,7 +383,7 @@ var ), (//[65] sy_narg:3; - sy_call:nil; + sy_call:@sys_msync; sy_name:'sys_msync' ), (//[66] @@ -1443,7 +1443,7 @@ var ), (//[277] sy_narg:3; - sy_call:nil; + sy_call:@sys_msync; sy_name:'sys_msync' ), (//[278] diff --git a/sys/syscalls.pas b/sys/syscalls.pas index 0daba27f..6bf3b9b7 100644 --- a/sys/syscalls.pas +++ b/sys/syscalls.pas @@ -45,6 +45,7 @@ function readlink(path,buf:PChar;count:QWORD):Integer; function _execve(fname:pchar;argv,envv:ppchar):Integer; function umask(newmask:Integer):Integer; function chroot(path:PChar):Integer; +function msync(addr:Pointer;len:QWORD;flags:Integer):Integer; function munmap(addr:Pointer;len:QWORD):Integer; function mprotect(addr:Pointer;len:QWORD;prot:Integer):Integer; function madvise(addr:Pointer;len:QWORD;behav:Integer):Integer; @@ -525,6 +526,13 @@ asm jmp cerror end; +function msync(addr:Pointer;len:QWORD;flags:Integer):Integer; assembler; nostackframe; +asm + movq $65,%rax + call fast_syscall + jmp cerror +end; + function munmap(addr:Pointer;len:QWORD):Integer; assembler; nostackframe; asm movq $73,%rax diff --git a/sys/vm/vm_map.pas b/sys/vm/vm_map.pas index eba736f8..4a20a391 100644 --- a/sys/vm/vm_map.pas +++ b/sys/vm/vm_map.pas @@ -225,6 +225,12 @@ function vm_map_madvise(map :vm_map_t; __end:vm_offset_t; behav:Integer):Integer; +function vm_map_sync(map :vm_map_t; + start :vm_offset_t; + __end :vm_offset_t; + syncio :Boolean; + invalidate:Boolean):Integer; + function vm_map_find(map :vm_map_t; vm_obj :vm_object_t; offset :vm_ooffset_t; @@ -257,7 +263,7 @@ function vm_map_stack(map :vm_map_t; function vm_map_growstack(map:vm_map_t;addr:vm_offset_t):Integer; function vmspace_exec(minuser,maxuser:vm_offset_t):Integer; -procedure vm_map_lock(map:vm_map_t); +procedure vm_map_lock(map:vm_map_t;tm:Boolean=True); function vm_map_trylock(map:vm_map_t):Boolean; procedure vm_map_unlock(map:vm_map_t); @@ -277,6 +283,7 @@ procedure vminit; //SYSINIT implementation uses + md_map, kern_proc, rmem_map, kern_budget; @@ -398,10 +405,13 @@ begin Result:=vm; end; -procedure vm_map_lock(map:vm_map_t); +procedure vm_map_lock(map:vm_map_t;tm:Boolean=True); begin mtx_lock(map^.lock); - Inc(map^.timestamp); + if tm then + begin + Inc(map^.timestamp); + end; end; function vm_map_trylock(map:vm_map_t):Boolean; @@ -2088,9 +2098,9 @@ end; * * Returns an error if any part of the specified range is not mapped. } -function vm_map_sync(map :vm_map_t; - start:vm_offset_t; - __end:vm_offset_t; +function vm_map_sync(map :vm_map_t; + start :vm_offset_t; + __end :vm_offset_t; syncio :Boolean; invalidate:Boolean):Integer; var @@ -2118,12 +2128,20 @@ begin start:=entry^.start; __end:=entry^.__end; end; + { * Make a first pass to check for user-wired memory and holes. } current:=entry; while (current<>@map^.header) and (current^.start<__end) do begin + if invalidate and + ((current^.eflags and MAP_ENTRY_USER_WIRED)<>0) then + begin + vm_map_unlock(map); + Exit(KERN_INVALID_ARGUMENT); + end; + if (__end>current^.__end) and ((current^.next=@map^.header) or (current^.__end<>current^.next^.start)) then @@ -2137,8 +2155,10 @@ begin if invalidate then begin - // + md_cacheflush(Pointer(start),__end-start,ICACHE or DCACHE); + //pmap_remove(map^.pmap, start, end); end; + failed:=FALSE; { @@ -2183,11 +2203,16 @@ begin vm_object_reference(obj); last_timestamp:=map^.timestamp; vm_map_unlock(map); - //if (not vm_object_sync(_object, offset, size, syncio, invalidate)) then - // failed:=TRUE; + + if (not vm_object_sync(obj, offset, size, syncio, invalidate)) then + begin + failed:=TRUE; + end; + start:=start+size; vm_object_deallocate(obj); - vm_map_lock(map); + + vm_map_lock(map,False); if (last_timestamp=map^.timestamp) or (not vm_map_lookup_entry(map, start, @current)) then begin diff --git a/sys/vm/vm_mmap.pas b/sys/vm/vm_mmap.pas index e016990f..aa46d8df 100644 --- a/sys/vm/vm_mmap.pas +++ b/sys/vm/vm_mmap.pas @@ -28,6 +28,7 @@ type pos :QWORD):Pointer; function sys_munmap(addr:Pointer;len:QWORD):Integer; +function sys_msync(addr:Pointer;len:QWORD;flags:Integer):Integer; function sys_mprotect(addr:Pointer;len:QWORD;prot:Integer):Integer; function sys_madvise(addr:Pointer;len:QWORD;behav:Integer):Integer; function sys_mname(addr:Pointer;len:QWORD;name:PChar):Integer; @@ -842,6 +843,50 @@ begin Exit(0); end; +function sys_msync(addr:Pointer;len:QWORD;flags:Integer):Integer; +var + map:vm_map_t; + _addr:vm_offset_t; + pageoff:vm_size_t; +begin + _addr:=vm_offset_t(addr); + + pageoff:=(_addr and PAGE_MASK); + _addr:=_addr-pageoff; + len:=len+pageoff; + + len:=round_page(len); + + if ((_addr + len) < _addr) then + begin + Exit(EINVAL); + end; + + if ((flags and (MS_ASYNC or MS_INVALIDATE))=(MS_ASYNC or MS_INVALIDATE)) then + begin + Exit(EINVAL); + end; + + map:=p_proc.p_vmspace; + + // Clean the pages and interpret the Exit value. + Result:=vm_map_sync(map, + _addr, + _addr + len, + (flags and MS_ASYNC)=0, + (flags and MS_INVALIDATE)<>0); + + case Result of + KERN_SUCCESS :Result:=0; + KERN_INVALID_ADDRESS :Result:=ENOMEM; + KERN_INVALID_ARGUMENT:Result:=EBUSY; + KERN_FAILURE :Result:=EIO; + else + Result:=EINVAL; + end; + +end; + function sys_mprotect(addr:Pointer;len:QWORD;prot:Integer):Integer; var size,pageoff:vm_size_t; diff --git a/sys/vm/vm_object.pas b/sys/vm/vm_object.pas index 403a8873..974e2db9 100644 --- a/sys/vm/vm_object.pas +++ b/sys/vm/vm_object.pas @@ -39,6 +39,12 @@ procedure vm_object_madvise(pmap :Pointer; __end :vm_offset_t; advise:Integer); +function vm_object_sync(obj :vm_object_t; + offset :vm_ooffset_t; + size :vm_size_t; + syncio :Boolean; + invalidate:Boolean):Boolean; + implementation uses @@ -504,6 +510,114 @@ begin VM_OBJECT_UNLOCK(obj); end; +{ + * Note that there is absolutely no sense in writing out + * anonymous objects, so we track down the vnode object + * to write out. + * We invalidate (remove) all pages from the address space + * for semantic correctness. + * + * If the backing object is a device object with unmanaged pages, then any + * mappings to the specified range of pages must be removed before this + * function is called. + * + * Note: certain anonymous maps, such as MAP_NOSYNC maps, + * may start out with a nil object. +} +function vm_object_sync(obj :vm_object_t; + offset :vm_ooffset_t; + size :vm_size_t; + syncio :Boolean; + invalidate:Boolean):Boolean; +var + vp:p_vnode; + mp:p_mount; + error,flags:Integer; + vfslocked:Integer; + fsync_after:Boolean; + res:Boolean; +begin + if (obj=nil) then Exit(TRUE); + + res:=TRUE; + error:=0; + VM_OBJECT_LOCK(obj); + + { + * Flush pages if writing is allowed, invalidate them + * if invalidation requested. Pages undergoing I/O + * will be ignored by vm_object_page_remove(). + * + * We cannot lock the vnode and then wait for paging + * to complete without deadlocking against vm_fault. + * Instead we simply call vm_object_page_remove() and + * allow it to block internally on a page-by-page + * basis when it encounters pages undergoing async + * I/O. + } + if (obj^.otype=OBJT_VNODE) and + ((obj^.flags and OBJ_MIGHTBEDIRTY)<>0) then + begin + vp:=obj^.handle; + VM_OBJECT_UNLOCK(obj); + vn_start_write(vp, @mp, V_WAIT); + vfslocked:=VFS_LOCK_GIANT(vp^.v_mount); + vn_lock(vp, LK_EXCLUSIVE or LK_RETRY); + + if (syncio) and + (not invalidate) and + (offset=0) and + (OFF_TO_IDX(size)=obj^.size) then + begin + { + * If syncing the whole mapping of the file, + * it is faster to schedule all the writes in + * async mode, also allowing the clustering, + * and then wait for i/o to complete. + } + flags:=0; + fsync_after:=TRUE; + end else + begin + flags:=0; + + if (syncio or invalidate) then + begin + flags:=flags or OBJPC_SYNC; + end; + + if (invalidate) then + begin + flags:=flags or (OBJPC_SYNC or OBJPC_INVAL); + end; + + fsync_after:=FALSE; + end; + + VM_OBJECT_LOCK(obj); + res:=vm_object_page_clean(obj, offset, offset + size, flags); + VM_OBJECT_UNLOCK(obj); + + if (fsync_after) then + begin + error:=VOP_FSYNC(vp, MNT_WAIT); + end; + + VOP_UNLOCK(vp, 0); + VFS_UNLOCK_GIANT(vfslocked); + vn_finished_write(mp); + + if (error<>0) then + begin + res:=FALSE; + end; + + VM_OBJECT_LOCK(obj); + end; + + VM_OBJECT_UNLOCK(obj); + Exit(res); +end;