diff --git a/gui/game_run.pas b/gui/game_run.pas index 02cc23fe..c149d02c 100644 --- a/gui/game_run.pas +++ b/gui/game_run.pas @@ -141,9 +141,12 @@ begin //g_appinfo.debug_level:=1; //budget init + kern_app_state_change(as_start); + kern_app_state_change(as_begin_game_app_mount); + p_proc.p_budget_ptype:=PTYPE_BIG_APP; - p_proc.p_self_fixed :=1; - p_proc.p_mode_2mb :=M2MB_DISABLE; + + g_mode_2mb:=M2MB_DEFAULT; /// Writeln(Item.FGameInfo.Exec); diff --git a/sys/init_sysent.pas b/sys/init_sysent.pas index 41495af6..1a6d9460 100644 --- a/sys/init_sysent.pas +++ b/sys/init_sysent.pas @@ -3298,7 +3298,7 @@ var ), (//[648] sy_narg:1; - sy_call:nil; + sy_call:@sys_app_state_change; sy_name:'sys_app_state_change' ), (//[649] diff --git a/sys/kern/kern_budget.pas b/sys/kern/kern_budget.pas index 9498dc15..fc33d7df 100644 --- a/sys/kern/kern_budget.pas +++ b/sys/kern/kern_budget.pas @@ -5,10 +5,6 @@ unit kern_budget; interface -uses - vm, - sys_vm_object; - type p_budget_resource=^t_budget_resource; t_budget_resource=packed record @@ -34,9 +30,9 @@ const SCE_KERNEL_BUDGET_FD_IPCSOCKET=11; //budget proc_type - PTYPE_BIG_APP = 0; - PTYPE_MINI_APP = 1; - PTYPE_SYSTEM = 2; + PTYPE_BIG_APP = 0; //SCE_APPLICATION_TYPE_GAME + PTYPE_MINI_APP = 1; //SCE_APPLICATION_TYPE_MINI + PTYPE_SYSTEM = 2; //SCE_APPLICATION_TYPE_DAEMON PTYPE_NONGAME_MINI_APP = 3; function sys_budget_create(name:pchar;ptype:DWORD;new:Pointer;count:DWORD;prev:Pointer):Integer; @@ -62,25 +58,39 @@ const field_malloc =3; const - FMEM_BASE =$4000000; - bigapp_size =$4000000; - bigapp_max_exe_size=$20000000; + FMEM_BASE =$4000000; + bigapp_size =$4000000; + bigapp_max_fmem_size=$20000000; var - FMEM_LIMIT :QWORD=0; - DMEM_LIMIT :QWORD=$180000000; - EXE_FILE_SIZE:QWORD=FMEM_BASE+0; - ExtendedSize :QWORD=0; + FMEM_LIMIT :QWORD=0; + DMEM_LIMIT :QWORD=$180000000; + game_fmem_size:QWORD=FMEM_BASE+0; + ExtendedSize :QWORD=0; - ext_game_fmem_addr:Integer=0; + BigAppMemory :QWORD=$170000000; //148000000,170000000,124000000 + + g_self_loading:Integer=0; + ext_game_fmem :Integer=0; IGNORE_EXTENDED_DMEM_BASE:Integer=0; -procedure set_budget_limit (ptype,field:Integer;value:QWORD); +const + M2MB_DEFAULT =0; //Default =0 (ATTRIBUTE2:0x00000) + M2MB_DISABLE =1; //NotUsed =32768 (ATTRIBUTE2:0x08000) + M2MB_READONLY=2; //Text_rodata=65536 (ATTRIBUTE2:0x10000) + M2MB_ENABLE =3; //All_section=98304 (ATTRIBUTE2:0x18000) + +var + g_mode_2mb :Integer=M2MB_DEFAULT; + g_mode_2mb_size:Integer=0; + g_mode_2mb_rsrv:Integer=0; + function vm_budget_limit (ptype,field:Integer):QWORD; function vm_budget_used (ptype,field:Integer):QWORD; function vm_budget_reserve(ptype,field:Integer;len:QWORD):Integer; procedure vm_budget_release(ptype,field:Integer;len:QWORD); +procedure init_bigapp_limits; procedure set_bigapp_cred_limits; procedure set_bigapp_limits(size,unknow:QWORD); @@ -89,6 +99,20 @@ function dmem_process_relocated():Integer; function get_mlock_avail():QWORD; function get_mlock_total():QWORD; +const + //app_state + as_start =1; + as_stop =2; + as_begin_game_app_mount =3; + as___end_game_app_mount =4; + as_begin_mini_app_mount =5; + as___end_mini_app_mount =6; + as__enable_ext_game_fmem=7; + as_disable_ext_game_fmem=8; + +function kern_app_state_change(state:Integer):Integer; +function sys_app_state_change(state:Integer):Integer; + implementation uses @@ -108,7 +132,7 @@ var budget_lock :Pointer; -procedure set_budget_limit(ptype,field:Integer;value:QWORD); +procedure vm_set_budget_limit(ptype,field:Integer;value:QWORD); begin rw_wlock(budget_lock); @@ -199,6 +223,37 @@ begin end; end; +procedure init_bigapp_limits; +var + size :QWORD; + value:QWORD; + m_256:QWORD; +begin + if (p_neomode<>0) then + begin + BigAppMemory:=$170000000; + end else + begin + BigAppMemory:=$148000000; + end; + + size:=BigAppMemory - game_fmem_size; + + m_256:=QWORD(ext_game_fmem<>0) * $10000000; + + value:=size; + if (FMEM_LIMIT <= size) then + begin + value:=FMEM_LIMIT; + end; + + DMEM_LIMIT:=size; + + vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,value); + vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); + vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + game_fmem_size); +end; + procedure set_bigapp_cred_limits; var size :QWORD; @@ -224,7 +279,7 @@ begin end; - m_256:=QWORD(ext_game_fmem_addr<>0) * $10000000; + m_256:=QWORD(ext_game_fmem<>0) * $10000000; value:=size; if (DMEM_LIMIT < size) then @@ -234,9 +289,9 @@ begin FMEM_LIMIT:=size; - set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,value); - set_budget_limit(PTYPE_BIG_APP,field_mlock ,(EXE_FILE_SIZE + m_256) - FMEM_BASE); - set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + EXE_FILE_SIZE); + vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,value); + vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); + vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + game_fmem_size); end; procedure set_bigapp_limits(size,unknow:QWORD); @@ -244,12 +299,28 @@ var m_256:QWORD; value:QWORD; begin - if (EXE_FILE_SIZE<>size) then + if (game_fmem_size<>size) then begin - //reserve dmem - EXE_FILE_SIZE:=size; - m_256:=QWORD(ext_game_fmem_addr<>0) * $10000000; + if (size < game_fmem_size) then + begin + value:=BigAppMemory - size; + game_fmem_size:=size; + DMEM_LIMIT :=value; + end else + begin + if (unknow<>0) and + ((game_fmem_size and $1fffff)<>0) then + begin + Writeln(stderr,'game_fmem_size is not multiple of 2MB: 0x',HexStr(game_fmem_size,8)); + end; + + value:=BigAppMemory - size; + game_fmem_size:=size; + DMEM_LIMIT :=value; + end; + + m_256:=QWORD(ext_game_fmem<>0) * $10000000; value:=FMEM_LIMIT; if (DMEM_LIMIT < FMEM_LIMIT) then @@ -257,19 +328,19 @@ begin value:=DMEM_LIMIT; end; - set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,value); - set_budget_limit(PTYPE_BIG_APP,field_mlock ,(EXE_FILE_SIZE + m_256) - FMEM_BASE); - set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + EXE_FILE_SIZE); + vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,value); + vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); + vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + game_fmem_size); end; end; function expand_and_reserve_game_fmem(size:QWORD):QWORD; begin - if (size <= QWORD(bigapp_max_exe_size - EXE_FILE_SIZE)) then + if (size <= QWORD(bigapp_max_fmem_size - game_fmem_size)) then begin - EXE_FILE_SIZE:=EXE_FILE_SIZE + size; - DMEM_LIMIT :=DMEM_LIMIT - size; - Exit(DMEM_LIMIT + size); + DMEM_LIMIT :=BigAppMemory - (game_fmem_size + size); + game_fmem_size:=game_fmem_size + size; + Exit(BigAppMemory - game_fmem_size); end; Writeln(stderr,'expand_and_reserve_game_fmem=',size); @@ -283,7 +354,7 @@ var begin Result:=expand_and_reserve_game_fmem(size); - m_256:=QWORD(ext_game_fmem_addr<>0) * $10000000; + m_256:=QWORD(ext_game_fmem<>0) * $10000000; value:=FMEM_LIMIT; if (DMEM_LIMIT < FMEM_LIMIT) then @@ -291,9 +362,9 @@ begin value:=DMEM_LIMIT; end; - set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,value); - set_budget_limit(PTYPE_BIG_APP,field_mlock ,(EXE_FILE_SIZE + m_256) - FMEM_BASE); - set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + EXE_FILE_SIZE); + vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,value); + vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); + vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + game_fmem_size); if (vm_budget_reserve(PTYPE_BIG_APP,field_mlock,size)<>0) then begin @@ -319,14 +390,16 @@ begin if ((GpuPagesSize or CpuPages)<> 0) then begin + size:=0; + if (param_3=0) then begin size:=(QWORD(ord(p_neomode=0)) * $800000) + GpuPagesSize + (CpuPages * $1000); - if (QWORD(bigapp_max_exe_size - EXE_FILE_SIZE) < size) then + if (QWORD(bigapp_max_fmem_size - game_fmem_size) < size) then begin Writeln('[KERNEL] WARNING: Failed to allocate extended page table pool. shortage = ' - ,(EXE_FILE_SIZE - bigapp_max_exe_size) + $fffff + (size shr 20), + ,(game_fmem_size - bigapp_max_fmem_size) + $fffff + (size shr 20), 'MiB'); Exit(ENOMEM); end; @@ -335,6 +408,8 @@ begin end; //reserved physical pages + + ExtendedSize:=size; end; end; @@ -412,9 +487,9 @@ begin _next: - if (Byte((mmap_flags xor 1) or ord(p_proc.p_self_fixed=0))=0) then + if (Byte((mmap_flags xor 1) or ord(g_self_loading=0))=0) then begin - p_proc.p_self_fixed:=0; + g_self_loading:=0; ExtendedMemory1:=true; if (p_proc.p_sdk_version < $5000000) then @@ -422,12 +497,14 @@ begin ExtendedMemory1:=fubyte(mem_param.sceKernelExtendedMemory1^)=1; end; - m_256:=QWORD(ext_game_fmem_addr<>0) * $10000000; + m_256:=QWORD(ext_game_fmem<>0) * $10000000; if (p_neomode<>0) and ((not ExtendedMemory1) or (IGNORE_EXTENDED_DMEM_BASE<>0)) then begin - FMEM_SIZE:=$10000000 - EXE_FILE_SIZE; + BigAppMemory:=BigAppMemory + (-$10000000) {+ ((ret or $10)=$19) * (-0x10000000)}; + + FMEM_SIZE:=BigAppMemory - game_fmem_size; size:=FMEM_SIZE; if (FMEM_LIMIT <= FMEM_SIZE) then @@ -437,9 +514,9 @@ begin DMEM_LIMIT:=FMEM_SIZE; - set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,size); - set_budget_limit(PTYPE_BIG_APP,field_mlock ,(EXE_FILE_SIZE + m_256) - FMEM_BASE); - set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + EXE_FILE_SIZE); + vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,size); + vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); + vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + game_fmem_size); end; ExtendedMemory2:=true; @@ -456,10 +533,11 @@ begin Writeln('[System] : SCE_KERNEL_EXTENDED_DMEM_BASE_128 was ignored'); end else begin - FMEM_SIZE:=$8000000 - EXE_FILE_SIZE; + BigAppMemory:=BigAppMemory + (-$8000000) {+ ((ret and $ffffffe7)=1) * (-$8000000)}; + + FMEM_SIZE:=BigAppMemory - game_fmem_size; size:=FMEM_SIZE; - if (FMEM_LIMIT <= FMEM_SIZE) then begin size:=FMEM_LIMIT; @@ -467,9 +545,9 @@ begin DMEM_LIMIT:=FMEM_SIZE; - set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,size); - set_budget_limit(PTYPE_BIG_APP,field_mlock ,(EXE_FILE_SIZE + m_256) - FMEM_BASE); - set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + EXE_FILE_SIZE); + vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,size); + vm_set_budget_limit(PTYPE_BIG_APP,field_mlock ,(game_fmem_size + m_256) - FMEM_BASE); + vm_set_budget_limit(PTYPE_BIG_APP,field_malloc ,m_256 + game_fmem_size); end; end; @@ -497,13 +575,13 @@ begin if (ExtendedGpuPageTable < $1000000001) then begin ExtendedSize:=0; - FMEM_SIZE:=bigapp_max_exe_size; + FMEM_SIZE:=bigapp_max_fmem_size; if (Result=0) then begin Result:=allocate_extended_page_table_pool(ExtendedCpuPageTable,ExtendedGpuPageTable,0); - FMEM_SIZE:=bigapp_max_exe_size; + FMEM_SIZE:=bigapp_max_fmem_size; if (Result=0) then begin @@ -515,19 +593,19 @@ begin FlexibleMemorySize:=fuword64(mem_param.sceKernelFlexibleMemorySize^); Result:=0; - FMEM_SIZE:=bigapp_max_exe_size; + FMEM_SIZE:=bigapp_max_fmem_size; if (FlexibleMemorySize<>QWORD($ffffffffffffffff)) then begin FMEM_SIZE:=FMEM_BASE + FlexibleMemorySize; - if (bigapp_max_exe_size < FMEM_SIZE) or + if (bigapp_max_fmem_size < FMEM_SIZE) or (FMEM_SIZE < bigapp_size) or ((FMEM_SIZE and QWORD($ffffffffffffc000))<>FMEM_SIZE) then begin Writeln(stderr,'[KERNEL] ERROR: invalid FMEM size (0x',HexStr(FlexibleMemorySize,16),') is specified.'); Result:=EINVAL; - FMEM_SIZE:=bigapp_max_exe_size; + FMEM_SIZE:=bigapp_max_fmem_size; end; end; end; @@ -539,12 +617,12 @@ begin Writeln('[KERNEL] ERROR: The extended GPU page table pool must be smaller than 64GiB'); Result:=ENOMEM; ExtendedSize:=0; - FMEM_SIZE:=bigapp_max_exe_size; + FMEM_SIZE:=bigapp_max_fmem_size; end; - if (FMEM_SIZE < EXE_FILE_SIZE) then + if (FMEM_SIZE < game_fmem_size) then begin - Writeln(stderr,'[KERNEL] ERROR: The executable file size (= 0x',HexStr(EXE_FILE_SIZE,16), + Writeln(stderr,'[KERNEL] ERROR: The executable file size (= 0x',HexStr(game_fmem_size,16), ') < specified FMEM size (=0x',HexStr(FMEM_SIZE,16),')'); if (Result=0) then begin @@ -662,6 +740,77 @@ begin Exit(ENOSYS); //sceSblACMgrIsSystemUcred end; +// + +function kern_app_state_change(state:Integer):Integer; +var + used:QWORD; +begin + Result:=0; + + case state of + as_start: + begin + g_self_loading:=1; + //app_state_counter+1 + end; + as_stop: + begin + g_self_loading:=0; + //app_state_counter-1 + end; + as_begin_game_app_mount: + begin + used:=vm_budget_used(PTYPE_BIG_APP,field_mlock); + if (used<>0) then + begin + Writeln(stderr,'BUDGET_MEMORY_MLOCK of game is being used: ',used,' bytes'); + Assert(false,'BUDGET_MEMORY_MLOCK'); + end; + end; + as___end_game_app_mount: + begin + //game_mounts_exist + //reset_2mb_mode + + vm_budget_release(PTYPE_BIG_APP,field_mlock,ExtendedSize); + ExtendedSize:=0; + + used:=vm_budget_used(PTYPE_BIG_APP,field_mlock); + if (used<>0) then + begin + Writeln(stderr,'BUDGET_MEMORY_MLOCK of game is being used: ',used,' bytes'); + Assert(false,'BUDGET_MEMORY_MLOCK'); + end; + + set_bigapp_limits(bigapp_size,0); + end; + as_begin_mini_app_mount:; //nothing + as___end_mini_app_mount:; //nothing + as__enable_ext_game_fmem: + begin + if (ext_game_fmem<>0) then + begin + Writeln(stderr,'ext_game_fmem is already enabled'); + Assert(false,'ext_game_fmem is already enabled'); + end; + + ext_game_fmem:=1; + end; + as_disable_ext_game_fmem: + begin + ext_game_fmem:=0; + end; + else; + end; +end; + +//sceKernelNotifyAppStateChanged +function sys_app_state_change(state:Integer):Integer; +begin + //sceSblACMgrIsSyscoreProcess + Exit(EPERM); +end; end. diff --git a/sys/kern/kern_exec.pas b/sys/kern/kern_exec.pas index 4b284114..19f3e489 100644 --- a/sys/kern/kern_exec.pas +++ b/sys/kern/kern_exec.pas @@ -293,14 +293,14 @@ begin //budget ssiz:=MAXSSIZ; - if (p_proc.p_self_fixed<>0) and + if (g_self_loading<>0) and (p_proc.p_budget_ptype=PTYPE_BIG_APP) and ((g_appinfo.mmap_flags and 1)<>0) then begin - limit:=EXE_FILE_SIZE + ssiz; - if (bigapp_max_exe_size < limit) then + limit:=game_fmem_size + ssiz; + if (bigapp_max_fmem_size < limit) then begin - limit:=bigapp_max_exe_size; + limit:=bigapp_max_fmem_size; end; set_bigapp_limits(limit,0); end; @@ -373,6 +373,11 @@ begin Exit(error); end; + //if (params->proc->vm_container == 1) { + // ret1 = vm_map_wire(vmspace,stack_addr,QWORD(vmspace^.sv_usrstack),9); + // if (ret1 != 0) goto __exit; + //} + vm_map_set_name(map,stack_addr,QWORD(vmspace^.sv_usrstack),'main stack'); { vm_ssize and vm_maxsaddr are somewhat antiquated concepts in the @@ -618,73 +623,6 @@ begin Exit(error); end; -procedure scan_max_size(imgp:p_image_params;phdr:p_elf64_phdr;count:Integer; - var max_size1,max_size2:QWORD); -var - i:Integer; - - hdr:p_elf64_hdr; - - p_memsz:QWORD; - p_vaddr:QWORD; - - size:QWORD; - base:QWORD; - - p_type:Elf64_Word; - - used_mode_2m:Boolean; -begin - max_size1:=0; - max_size2:=0; - - hdr:=imgp^.image_header; - - if (count<>0) then - begin - For i:=0 to count-1 do - begin - p_type :=phdr^.p_type; - p_memsz:=phdr^.p_memsz; - - if ((p_type=PT_SCE_RELRO) or (p_type=PT_LOAD)) and (p_memsz<>0) then - begin - - p_vaddr:=phdr^.p_vaddr; - - if (hdr^.e_type=ET_SCE_DYNEXEC) then - begin - p_vaddr:=p_vaddr + QWORD(imgp^.reloc_base); - end; - - p_memsz:=p_vaddr and $ffffffffffffc000; - - p_vaddr:=(phdr^.p_memsz + p_vaddr - p_memsz + $3fff) and $ffffffffffffc000; - - max_size1:=max_size1+p_vaddr; - - used_mode_2m:=is_used_mode_2mb(phdr,0,p_proc.p_budget_ptype); - - if (used_mode_2m) then - begin - size :=(p_vaddr + p_memsz) and $ffffffffffe00000; - p_vaddr:=(p_memsz + $1fffff) and $ffffffffffe00000; - base:=0; - if (p_vaddr<=size) then - begin - base:=size-p_vaddr; - end; - max_size2:=max_size2+base; - end; - - end; - - Inc(phdr); - end; - end; - -end; - function scan_load_sections(imgp:p_image_params;phdr:p_elf64_phdr;count:Integer):Integer; var i:Integer; @@ -709,6 +647,9 @@ var addr:QWORD; size:QWORD; + used :QWORD; + limit:QWORD; + p_type :Elf64_Word; p_flags :Byte; _2mb_mode:Boolean; @@ -734,9 +675,9 @@ begin if (p_proc.p_budget_ptype=PTYPE_BIG_APP) then begin - //M2MB_READONLY,M2MB_ENABLE - _2mb_mode:=((p_proc.p_mode_2mb or 1)=3) or - ((p_proc.p_self_fixed<>0) and (p_proc.p_mode_2mb=M2MB_NOTDYN_FIXED)); + + _2mb_mode:=((g_mode_2mb or 1)=3) or //M2MB_READONLY,M2MB_ENABLE + ((g_self_loading<>0) and (g_mode_2mb=M2MB_DEFAULT)); end else begin _2mb_mode:=False; @@ -752,41 +693,41 @@ begin scan_max_size(imgp,phdr,count,max_size1,max_size2); if ((g_appinfo.mmap_flags and 1)<>0) and - (p_proc.p_self_fixed<>0) then + (g_self_loading<>0) then begin - size:=p_proc.p_mode_2mb_size; - if (max_size2 < p_proc.p_mode_2mb_size) then + size:=g_mode_2mb_size; + if (max_size2 < g_mode_2mb_size) then begin size:=max_size2; end; p_offset:=0; - if ((p_proc.p_mode_2mb or 1)=3) then + if ((g_mode_2mb or 1)=3) then //M2MB_READONLY,M2MB_ENABLE begin p_offset:=size; end; - p_memsz:=EXE_FILE_SIZE + max_size1; + p_memsz:=game_fmem_size + max_size1; - if (bigapp_max_exe_size < (p_memsz - p_offset)) then + if (bigapp_max_fmem_size < (p_memsz - p_offset)) then begin Writeln(stderr,'vm_budget ENOMEM'); Exit(ENOMEM); end; - if ((DWORD(p_proc.p_mode_2mb) - 2) < 2) then + if ((DWORD(g_mode_2mb) - 2) < 2) then begin p_memsz:=p_memsz - size; size:=0; end else begin - if (p_proc.p_mode_2mb=M2MB_DISABLE) then + if (g_mode_2mb=M2MB_DISABLE) then begin size:=0; end else begin size:=max_size2; - if (p_proc.p_mode_2mb<>M2MB_NOTDYN_FIXED) then + if (g_mode_2mb<>M2MB_DEFAULT) then begin Writeln(stderr,'unknown 2mb mode'); Assert(false,'unknown 2mb mode'); @@ -794,26 +735,26 @@ begin end; end; - if (bigapp_max_exe_size < p_memsz) then + if (bigapp_max_fmem_size < p_memsz) then begin - p_memsz:=bigapp_max_exe_size; + p_memsz:=bigapp_max_fmem_size; end; set_bigapp_limits(p_memsz,size); end; - if ((p_proc.p_mode_2mb and $fffffffe)=M2MB_READONLY) then + if ((g_mode_2mb and $fffffffe)=2) then //M2MB_READONLY,M2MB_ENABLE begin - size:=p_proc.p_mode_2mb_rsrv; + size:=g_mode_2mb_rsrv; if (size<=max_size2) then begin - max_size2:=p_proc.p_mode_2mb_rsrv; + max_size2:=g_mode_2mb_rsrv; end; - p_vaddr :=vm_budget_used (PTYPE_BIG_APP,field_mlock); - p_offset:=vm_budget_limit(PTYPE_BIG_APP,field_mlock); + used :=vm_budget_used (PTYPE_BIG_APP,field_mlock); + limit:=vm_budget_limit(PTYPE_BIG_APP,field_mlock); - if (p_offset < (p_vaddr + (max_size1 - max_size2))) then + if (limit < (used + (max_size1 - max_size2))) then begin Writeln(stderr,'vm_budget ENOMEM'); Exit(ENOMEM); @@ -862,6 +803,7 @@ begin p_memsz, p_filesz, p_flags, + 0, used_mode_2m, 'executable', cache); @@ -884,6 +826,7 @@ begin p_memsz, p_filesz, p_flags, + 0, used_mode_2m, 'executable', cache); @@ -1514,6 +1457,15 @@ begin imgp:=@image_params; image_params:=Default(t_image_params); + if (p_proc.p_budget_ptype=PTYPE_BIG_APP) then + if ((g_appinfo.mmap_flags and 1)<>0) then + begin + if (g_self_loading<>0) then + begin + init_bigapp_limits; + end; + end; + p_proc.p_flag:=p_proc.p_flag or P_INEXEC; { diff --git a/sys/kern/kern_proc.pas b/sys/kern/kern_proc.pas index a462fb31..9ff3259d 100644 --- a/sys/kern/kern_proc.pas +++ b/sys/kern/kern_proc.pas @@ -59,13 +59,8 @@ var p_vmspace:Pointer; - p_self_fixed :Integer; p_budget_ptype :Integer; p_dmem_aliasing:Integer; - - p_mode_2mb :Integer; - p_mode_2mb_size:Integer; - p_mode_2mb_rsrv:Integer; end; function pargs_alloc(len:Integer):p_pargs; diff --git a/sys/kern/kern_rtld.pas b/sys/kern/kern_rtld.pas index b12abafa..2e905e4d 100644 --- a/sys/kern/kern_rtld.pas +++ b/sys/kern/kern_rtld.pas @@ -148,16 +148,10 @@ type hdr_e_type:Integer; end; -const - M2MB_NOTDYN_FIXED=0; //Default =0 (ATTRIBUTE2:0x00000) - M2MB_DISABLE =1; //NotUsed =32768 (ATTRIBUTE2:0x08000) - M2MB_READONLY =2; //Text_rodata=65536 (ATTRIBUTE2:0x10000) - M2MB_ENABLE =3; //All_section=98304 (ATTRIBUTE2:0x18000) - function maxInt64(a,b:Int64):Int64; inline; function minInt64(a,b:Int64):Int64; inline; -function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr; inline; +function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr; procedure rtld_free_self(imgp:p_image_params); function rtld_load_self(imgp:p_image_params):Integer; @@ -188,6 +182,7 @@ function scan_dyn_offset(imgp:p_image_params;phdr:p_elf64_phdr;count:Integer):I function self_load_section(imgp:p_image_params; id,vaddr,offset,memsz,filesz:QWORD; prot:Byte; + wire:Byte; use_mode_2mb:Boolean; name:pchar; var cache:Pointer):Integer; @@ -511,10 +506,10 @@ begin flag_write:=phdr^.p_flags and 2; end; - case p_proc.p_mode_2mb of - M2MB_NOTDYN_FIXED:Result:=(is_dynlib=0) and (p_proc.p_self_fixed<>0); - M2MB_READONLY :Result:=(flag_write=0); - M2MB_ENABLE :Result:=True; + case g_mode_2mb of + M2MB_DEFAULT :Result:=(is_dynlib=0) and (g_self_loading<>0); + M2MB_READONLY:Result:=(flag_write=0); + M2MB_ENABLE :Result:=True; else; end; @@ -1044,6 +1039,7 @@ end; function self_load_section(imgp:p_image_params; id,vaddr,offset,memsz,filesz:QWORD; prot:Byte; + wire:Byte; use_mode_2mb:Boolean; name:pchar; var cache:Pointer):Integer; @@ -1051,6 +1047,7 @@ var map:vm_map_t; vaddr_lo:QWORD; vaddr_hi:QWORD; + size :QWORD; base :Pointer; begin Result:=0; @@ -1073,15 +1070,29 @@ begin Exit(ENOEXEC); end; - vaddr_lo:=vaddr and $ffffffffffffc000; - vaddr_hi:=(memsz + vaddr + $3fff) and $ffffffffffffc000; - - if (use_mode_2mb) then + if (filesz < memsz) then begin - vaddr_lo:=(vaddr + $1fffff) and $ffffffffffe00000; - vaddr_hi:=(vaddr + memsz + $3fff) and $ffffffffffe00000; + if (use_mode_2mb) then + begin + size:=QWORD($ffffffffffe00000); + end else + begin + size:=QWORD($ffffffffffffc000); + end; + size:=size and filesz; + end else + begin + size:=(filesz + $3fff) and QWORD($ffffffffffffc000); end; + if (size>memsz) then + begin + memsz:=size; + end; + + vaddr_lo:=vaddr and QWORD($ffffffffffffc000); + vaddr_hi:=(vaddr + memsz + $3fff) and QWORD($ffffffffffffc000); + base:=Pointer(imgp^.image_header)+offset; map:=p_proc.p_vmspace; @@ -1100,22 +1111,19 @@ begin // vm_object_deallocate(imgp^.obj); // + Writeln(StdErr,'[',HexStr(vaddr_lo,8),'..',HexStr(vaddr_hi,8),']'); Writeln(StdErr,'[KERNEL] self_load_section: vm_map_insert failed ',id,', ',HexStr(vaddr,8)); Exit(vm_mmap_to_errno(Result)); end; vm_map_set_name_locked(map,vaddr_lo,vaddr_hi,name); + //wire + memsz:=vaddr_hi-vaddr_lo; cache:=ReAllocMem(cache,memsz); - if ((prot and VM_PROT_EXECUTE)<>0) then - begin - FillChar(cache^,memsz,$90); - end else - begin - FillChar(cache^,memsz,0); - end; + FillChar(cache^,memsz,0); Move(base^,cache^,filesz); diff --git a/sys/kern/subr_backtrace.pas b/sys/kern/subr_backtrace.pas index eb8ee1f5..f0516d72 100644 --- a/sys/kern/subr_backtrace.pas +++ b/sys/kern/subr_backtrace.pas @@ -275,14 +275,14 @@ begin offset1:=QWORD(frame)-QWORD(info.base_addr); offset2:=QWORD(frame)-QWORD(info.func_addr); - Writeln(f,' offset $',HexStr(offset1 shr 48,5),'|',HexStr(offset1,6),' ',info.source,':',info.func,'+$',HexStr(offset2,6)); + Writeln(f,' offset $',HexStr(offset1 shr 24,5),'|',HexStr(offset1,6),' ',info.source,':',info.func,'+$',HexStr(offset2,6)); end else begin if (info.base_addr<>0) then begin offset1:=QWORD(frame)-QWORD(info.base_addr); - Writeln(f,' offset $',HexStr(offset1 shr 48,5),'|',HexStr(offset1,6),' ',info.source); + Writeln(f,' offset $',HexStr(offset1 shr 24,5),'|',HexStr(offset1,6),' ',info.source); end else begin Writeln(f,' $',HexStr(frame),' ',info.source); diff --git a/sys/kern/subr_dynlib.pas b/sys/kern/subr_dynlib.pas index 891525c0..39d83684 100644 --- a/sys/kern/subr_dynlib.pas +++ b/sys/kern/subr_dynlib.pas @@ -302,6 +302,10 @@ function check_relo_bits(obj:p_lib_info;i:Integer):Boolean; procedure set_relo_bits (obj:p_lib_info;i:Integer); procedure reset_relo_bits(obj:p_lib_info;i:Integer); +procedure scan_max_size(imgp:p_image_params; + phdr:p_elf64_phdr;count:Integer; + var max_size1,max_size2:QWORD); + procedure donelist_init(var dlp:t_DoneList); function donelist_check(var dlp:t_DoneList;obj:p_lib_info):Boolean; @@ -1716,7 +1720,7 @@ begin p^:=p^ and (not (1 shl (i and 7))); end; -function dynlib_load_sections(imgp:p_image_params;new:p_lib_info;phdr:p_elf64_phdr;count:Integer;delta:QWORD):Integer; +function dynlib_load_sections(imgp:p_image_params;new:p_lib_info;phdr:p_elf64_phdr;count:Integer;delta:QWORD;wire:Integer):Integer; var i:Integer; @@ -1757,7 +1761,7 @@ begin if (p_proc.p_budget_ptype=PTYPE_BIG_APP) then begin - _2mb_mode:=((p_proc.p_mode_2mb or 1)=3); + _2mb_mode:=((g_mode_2mb or 1)=3); //M2MB_READONLY,M2MB_ENABLE end else begin _2mb_mode:=False; @@ -1803,6 +1807,7 @@ begin p_memsz, p_filesz, p_flags, + wire, used_mode_2m, fname, cache); @@ -1825,6 +1830,7 @@ begin p_memsz, p_filesz, p_flags, + wire, used_mode_2m, fname, cache); @@ -1915,6 +1921,74 @@ begin new^.relro_size :=imgp^.relro_size; end; +procedure scan_max_size(imgp:p_image_params; + phdr:p_elf64_phdr;count:Integer; + var max_size1,max_size2:QWORD); +var + i:Integer; + + hdr:p_elf64_hdr; + + p_memsz:QWORD; + p_vaddr:QWORD; + + size:QWORD; + base:QWORD; + + p_type:Elf64_Word; + + used_mode_2m:Boolean; +begin + max_size1:=0; + max_size2:=0; + + hdr:=imgp^.image_header; + + if (count<>0) then + begin + For i:=0 to count-1 do + begin + p_type :=phdr^.p_type; + p_memsz:=phdr^.p_memsz; + + if ((p_type=PT_SCE_RELRO) or (p_type=PT_LOAD)) and (p_memsz<>0) then + begin + + p_vaddr:=phdr^.p_vaddr; + + if (hdr^.e_type=ET_SCE_DYNEXEC) then + begin + p_vaddr:=p_vaddr + QWORD(imgp^.reloc_base); + end; + + p_memsz:=p_vaddr and QWORD($ffffffffffffc000); + + p_vaddr:=(phdr^.p_memsz + p_vaddr - p_memsz + $3fff) and QWORD($ffffffffffffc000); + + max_size1:=max_size1+p_vaddr; + + used_mode_2m:=is_used_mode_2mb(phdr,0,p_proc.p_budget_ptype); + + if (used_mode_2m) then + begin + size :=(p_vaddr + p_memsz) and QWORD($ffffffffffe00000); + p_vaddr:=(p_memsz + $1fffff) and QWORD($ffffffffffe00000); + base:=0; + if (p_vaddr<=size) then + begin + base:=size-p_vaddr; + end; + max_size2:=max_size2+base; + end; + + end; + + Inc(phdr); + end; + end; + +end; + function self_load_shared_object(path:pchar;new:p_lib_info;wire:Integer):Integer; label _fail_dealloc; @@ -1932,6 +2006,11 @@ var phdr:p_elf64_phdr; addr,delta:QWORD; + + max_size1:QWORD; + max_size2:QWORD; + used :QWORD; + limit :QWORD; begin Result:=-1; if (path=nil) then Exit; @@ -2075,6 +2154,27 @@ begin addr:=ET_DYN_LOAD_ADDR_SYS; end; + if ((g_mode_2mb and DWORD($fffffffe))=2) then //M2MB_READONLY,M2MB_ENABLE + begin + max_size1:=0; + max_size2:=0; + scan_max_size(imgp,phdr,hdr^.e_phnum,max_size1,max_size2); + + if (max_size2 > g_mode_2mb_rsrv) then + begin + max_size2:=g_mode_2mb_rsrv; + end; + + used :=vm_budget_used (PTYPE_BIG_APP,field_mlock); + limit:=vm_budget_limit(PTYPE_BIG_APP,field_mlock); + + if ((used + (max_size1 - max_size2)) > limit) then + begin + error:=ENOMEM; + goto _fail_dealloc; + end; + end; + error:=rtld_mmap(@addr,imgp^.max_addr-imgp^.min_addr); if (error<>0) then begin @@ -2097,7 +2197,7 @@ begin 1, 0); - error:=dynlib_load_sections(imgp,new,phdr,hdr^.e_phnum,delta); + error:=dynlib_load_sections(imgp,new,phdr,hdr^.e_phnum,delta,wire); if (error<>0) then begin goto _fail_dealloc; diff --git a/sys/syscalls.pas b/sys/syscalls.pas index 6bf3b9b7..9ee781f0 100644 --- a/sys/syscalls.pas +++ b/sys/syscalls.pas @@ -146,7 +146,7 @@ function setcontext(ucp:Pointer):Integer; function swapcontext(oucp,ucp:Pointer):Integer; Function sigwait(oset:Pointer;sig:PInteger):Integer; function thr_create(ctx:Pointer;id:PDWORD;flags:Integer):Integer; -procedure thr_exit(state:PQWORD); +procedure thr_exit(state:PDWORD); function thr_self(id:PDWORD):Integer; function thr_kill(id,sig:Integer):Integer; function _umtx_lock(mtx:Pointer):Integer; @@ -243,6 +243,7 @@ function set_timezone_info(data_ptr:Pointer;data_count_dw:Integer):Integer; function utc_to_localtime(time:QWORD;local_time,tsec:Pointer;dstsec:PInteger):Integer; function localtime_to_utc(time:QWORD;tz_type:Integer;utc_time,tsec:Pointer;dstsec:PInteger):Integer; function set_chicken_switches(flags:Integer):Integer; +function app_state_change(state:Integer):Integer; function dynlib_get_obj_member(handle:Integer;num:Byte;pout:PPointer):Integer; function budget_get_ptype_of_budget(key:Integer):Integer; function blockpool_open(flags:Integer):Integer; @@ -1233,7 +1234,7 @@ asm jmp cerror end; -procedure thr_exit(state:PQWORD); assembler; nostackframe; +procedure thr_exit(state:PDWORD); assembler; nostackframe; asm movq $431,%rax call fast_syscall @@ -1912,6 +1913,13 @@ asm jmp cerror end; +function app_state_change(state:Integer):Integer; assembler; nostackframe; +asm + movq $648,%rax + call fast_syscall + jmp cerror +end; + function dynlib_get_obj_member(handle:Integer;num:Byte;pout:PPointer):Integer; assembler; nostackframe; asm movq $649,%rax