mirror of https://github.com/red-prig/fpPS4.git
1053 lines
23 KiB
Plaintext
1053 lines
23 KiB
Plaintext
unit kern_budget;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
type
|
|
p_budget_resource=^t_budget_resource;
|
|
t_budget_resource=packed record
|
|
resid:Integer;
|
|
attr :Integer;
|
|
limit:QWORD; //cpuset
|
|
used :QWORD;
|
|
end;
|
|
|
|
//budget resid
|
|
const
|
|
SCE_KERNEL_BUDGET_INVALID =0;
|
|
SCE_KERNEL_BUDGET_MEMORY_DMEM =1;
|
|
SCE_KERNEL_BUDGET_MEMORY_VMEM =2;
|
|
SCE_KERNEL_BUDGET_MEMORY_MLOCK=3;
|
|
SCE_KERNEL_BUDGET_CPU_SET =4;
|
|
SCE_KERNEL_BUDGET_FD_FILE =5;
|
|
SCE_KERNEL_BUDGET_FD_SOCKET =6;
|
|
SCE_KERNEL_BUDGET_FD_EQUEUE =7;
|
|
SCE_KERNEL_BUDGET_FD_PIPE =8;
|
|
SCE_KERNEL_BUDGET_FD_DEVICE =9;
|
|
SCE_KERNEL_BUDGET_THREADS =10;
|
|
SCE_KERNEL_BUDGET_FD_IPCSOCKET=11;
|
|
|
|
//budget proc_type
|
|
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;
|
|
function sys_budget_delete(key:Integer):Integer;
|
|
function sys_budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer;
|
|
function sys_budget_set(key:Integer):Integer;
|
|
function sys_budget_get_ptype(pid:Integer):Integer;
|
|
function sys_budget_get_ptype_of_budget(key:Integer):Integer;
|
|
function sys_budget_getid():Integer;
|
|
|
|
//internals
|
|
type
|
|
t_budget_info=packed record
|
|
zero :QWORD;
|
|
dmem_alloc:QWORD;
|
|
malloc :QWORD;
|
|
mlock :QWORD;
|
|
end;
|
|
|
|
const
|
|
field_dmem_alloc=1;
|
|
field_mlock =2;
|
|
field_malloc =3;
|
|
|
|
const
|
|
FMEM_BASE =$4000000; //64MB Minimum reserved size of flex memory at system startup
|
|
bigapp_size =$4000000;
|
|
bigapp_max_fmem_size=$20000000; //512MB Maximum possible size of flex memory
|
|
|
|
DUH_D1xxx:Boolean =False; //Development Mode in the DUH-D1xxx series
|
|
|
|
var
|
|
FMEM_LIMIT :QWORD=0;
|
|
DMEM_LIMIT :QWORD=$180000000; // 6144MB
|
|
game_fmem_size:QWORD=bigapp_size;
|
|
ExtendedSize :QWORD=0;
|
|
|
|
//148000000 5248MB
|
|
//170000000 5888MB
|
|
//124000000 4672MB
|
|
BigAppMemory :QWORD=$170000000; // dmem_size + game_fmem_size
|
|
|
|
g_self_loading :Integer=0;
|
|
g_ext_game_fmem:Integer=0; //Enabling extended fmem size +256MB
|
|
IGNORE_EXTENDED_DMEM_BASE:Integer=0;
|
|
|
|
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_DISABLE;
|
|
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,is_2MB_align:QWORD);
|
|
|
|
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;
|
|
|
|
procedure reset_2mb_mode;
|
|
function kern_reserve_2mb_page(size:QWORD;mode:Integer):Integer;
|
|
function sys_reserve_2mb_page (size:QWORD;mode:Integer):Integer;
|
|
|
|
implementation
|
|
|
|
uses
|
|
errno,
|
|
sys_bootparam,
|
|
kern_thr,
|
|
kern_proc,
|
|
kern_rwlock,
|
|
systm,
|
|
vmparam,
|
|
elf64,
|
|
subr_dynlib,
|
|
kern_authinfo;
|
|
|
|
var
|
|
budget_limit :t_budget_info;
|
|
budget_reserve:t_budget_info;
|
|
|
|
budget_lock :Pointer;
|
|
|
|
procedure vm_set_budget_limit(ptype,field:Integer;value:QWORD);
|
|
begin
|
|
case field of
|
|
field_dmem_alloc:Writeln('vm_set_budget_limit(dmem_alloc,0x',HexStr(value,16),')');
|
|
field_mlock :Writeln('vm_set_budget_limit(mlock ,0x',HexStr(value,16),')');
|
|
field_malloc :Writeln('vm_set_budget_limit(malloc ,0x',HexStr(value,16),')');
|
|
else;
|
|
end;
|
|
|
|
rw_wlock(budget_lock);
|
|
|
|
//TODO: ptype/budget_id ignored
|
|
PQWORD(@budget_limit)[field]:=value;
|
|
|
|
rw_wunlock(budget_lock);
|
|
end;
|
|
|
|
function vm_budget_limit(ptype,field:Integer):QWORD;
|
|
begin
|
|
rw_wlock(budget_lock);
|
|
|
|
//TODO: ptype/budget_id ignored
|
|
Result:=PQWORD(@budget_limit)[field];
|
|
|
|
rw_wunlock(budget_lock);
|
|
end;
|
|
|
|
function vm_budget_used(ptype,field:Integer):QWORD;
|
|
begin
|
|
rw_wlock(budget_lock);
|
|
|
|
//TODO: ptype/budget_id ignored
|
|
Result:=PQWORD(@budget_reserve)[field];
|
|
|
|
rw_wunlock(budget_lock);
|
|
end;
|
|
|
|
function vm_budget_reserve(ptype,field:Integer;len:QWORD):Integer;
|
|
var
|
|
rsv,limit:QWORD;
|
|
begin
|
|
if (ptype<PTYPE_BIG_APP) or (len=0) then
|
|
begin
|
|
Result:=0;
|
|
end else
|
|
begin
|
|
rw_wlock(budget_lock);
|
|
|
|
//TODO: ptype/budget_id ignored
|
|
|
|
rsv :=PQWORD(@budget_reserve)[field];
|
|
limit:=PQWORD(@budget_limit )[field];
|
|
|
|
{
|
|
if field=3 then
|
|
begin
|
|
Writeln('vm_budget_reserve:',' rsv=0x',HexStr(rsv,10),' limit=0x',HexStr(limit,10),' len=0x',HexStr(len,10));
|
|
end;
|
|
}
|
|
|
|
if (rsv <= limit) and
|
|
(len <= (limit - rsv)) then
|
|
begin
|
|
PQWORD(@budget_reserve)[field]:=rsv + len;
|
|
Result:=0;
|
|
end else
|
|
begin
|
|
Result:=ENOMEM;
|
|
end;
|
|
|
|
rw_wunlock(budget_lock);
|
|
end;
|
|
end;
|
|
|
|
procedure vm_budget_release(ptype,field:Integer;len:QWORD);
|
|
var
|
|
rsv,size:QWORD;
|
|
begin
|
|
if (ptype > -1) and (len<>0) then
|
|
begin
|
|
rw_wlock(budget_lock);
|
|
|
|
//TODO: ptype/budget_id ignored
|
|
|
|
rsv:=PQWORD(@budget_reserve)[field];
|
|
|
|
size:=0;
|
|
if (len <= rsv) then
|
|
begin
|
|
size:=rsv - len;
|
|
end;
|
|
|
|
PQWORD(@budget_reserve)[field]:=size;
|
|
|
|
rw_wunlock(budget_lock);
|
|
end;
|
|
end;
|
|
|
|
procedure init_bigapp_limits;
|
|
var
|
|
dmem_size :QWORD;
|
|
limit_value:QWORD;
|
|
m_256 :QWORD;
|
|
begin
|
|
if (p_neomode<>0) then
|
|
begin
|
|
BigAppMemory:=$170000000; //5888MB
|
|
end else
|
|
begin
|
|
BigAppMemory:=$148000000; //5248MB
|
|
end;
|
|
|
|
dmem_size:=BigAppMemory - game_fmem_size;
|
|
|
|
//[0..dmem_size),[game_fmem_size..BigAppMemory)
|
|
|
|
//TODO: realloc dmem (DMEM_LIMIT->dmem_size)
|
|
|
|
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
|
|
|
|
limit_value:=dmem_size;
|
|
if (FMEM_LIMIT <= dmem_size) then
|
|
begin
|
|
limit_value:=FMEM_LIMIT;
|
|
end;
|
|
|
|
DMEM_LIMIT:=dmem_size;
|
|
|
|
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_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 ,(game_fmem_size + m_256));
|
|
end;
|
|
|
|
procedure set_bigapp_cred_limits;
|
|
var
|
|
size :QWORD;
|
|
limit_value:QWORD;
|
|
m_256 :QWORD;
|
|
ret :Boolean;
|
|
begin
|
|
ret:=is_sce_prog_attr_20_800000(@g_appinfo);
|
|
|
|
if (ret) then
|
|
begin
|
|
size:=$a0000000; //2GB
|
|
end else
|
|
begin
|
|
ret:=is_sce_prog_attr_20_400000(@g_appinfo);
|
|
|
|
if ret then
|
|
begin
|
|
size:=$30000000; //768MB
|
|
end else
|
|
begin
|
|
size:=QWORD(-1);
|
|
end;
|
|
|
|
end;
|
|
|
|
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
|
|
|
|
limit_value:=size;
|
|
if (DMEM_LIMIT < size) then
|
|
begin
|
|
limit_value:=DMEM_LIMIT;
|
|
end;
|
|
|
|
FMEM_LIMIT:=size;
|
|
|
|
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_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 ,(game_fmem_size + m_256));
|
|
end;
|
|
|
|
procedure set_bigapp_limits(size,is_2MB_align:QWORD);
|
|
var
|
|
m_256 :QWORD;
|
|
limit_value:QWORD;
|
|
begin
|
|
if (game_fmem_size<>size) then
|
|
begin
|
|
|
|
if (size < game_fmem_size) then
|
|
begin
|
|
//expand
|
|
|
|
//TODO: realloc fmem (game_fmem_size->size) (switch_from_fmem)
|
|
|
|
limit_value :=BigAppMemory - size;
|
|
|
|
//TODO: realloc dmem (DMEM_LIMIT->limit_value)
|
|
|
|
game_fmem_size:=size;
|
|
DMEM_LIMIT :=limit_value;
|
|
end else
|
|
begin
|
|
//shrink
|
|
|
|
if (is_2MB_align<>0) and
|
|
((game_fmem_size and PAGE_2MB_MASK)<>0) then
|
|
begin
|
|
Writeln(stderr,'game_fmem_size is not multiple of 2MB: 0x',HexStr(game_fmem_size,8));
|
|
end;
|
|
|
|
limit_value :=BigAppMemory - size;
|
|
|
|
//TODO: realloc dmem (DMEM_LIMIT->limit_value)
|
|
|
|
//TODO: realloc fmem (game_fmem_size->size) (switch_to_fmem)
|
|
|
|
game_fmem_size:=size;
|
|
|
|
DMEM_LIMIT :=limit_value;
|
|
end;
|
|
|
|
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
|
|
|
|
limit_value:=FMEM_LIMIT;
|
|
if (DMEM_LIMIT < FMEM_LIMIT) then
|
|
begin
|
|
limit_value:=DMEM_LIMIT;
|
|
end;
|
|
|
|
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_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 ,(game_fmem_size + m_256));
|
|
end;
|
|
end;
|
|
|
|
function expand_and_reserve_game_fmem(size:QWORD):QWORD;
|
|
var
|
|
dmem_size:QWORD;
|
|
begin
|
|
if (size <= QWORD(bigapp_max_fmem_size - game_fmem_size)) then
|
|
begin
|
|
dmem_size:=BigAppMemory - (game_fmem_size + size);
|
|
|
|
//TODO: realloc dmem (DMEM_LIMIT->dmem_size)
|
|
|
|
DMEM_LIMIT:=dmem_size;
|
|
|
|
//TODO: realloc fmem (game_fmem_size->(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);
|
|
Assert(false,'expand_and_reserve_game_fmem');
|
|
end;
|
|
|
|
function expand_budget_limit(size:QWORD):QWORD;
|
|
var
|
|
m_256 :QWORD;
|
|
limit_value:QWORD;
|
|
begin
|
|
Result:=expand_and_reserve_game_fmem(size);
|
|
|
|
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
|
|
|
|
limit_value:=FMEM_LIMIT;
|
|
if (DMEM_LIMIT < FMEM_LIMIT) then
|
|
begin
|
|
limit_value:=DMEM_LIMIT;
|
|
end;
|
|
|
|
vm_set_budget_limit(PTYPE_BIG_APP,field_dmem_alloc,limit_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 ,(game_fmem_size + m_256));
|
|
|
|
if (vm_budget_reserve(PTYPE_BIG_APP,field_mlock,size)<>0) then
|
|
begin
|
|
Writeln(stderr,'wrong MLOCK budget accounting');
|
|
Assert(false,'wrong MLOCK budget accounting');
|
|
end;
|
|
end;
|
|
|
|
function allocate_extended_page_table_pool(ExtendedCpuPageTable:QWORD;
|
|
ExtendedGpuPageTable:QWORD;
|
|
param_3:QWORD):Integer;
|
|
var
|
|
GpuPages:QWORD;
|
|
CpuPages:QWORD;
|
|
GpuPagesSize:QWORD;
|
|
size:QWORD;
|
|
begin
|
|
Result:=0;
|
|
|
|
GpuPages:=(ExtendedGpuPageTable + $7fffff) shr 23;
|
|
CpuPages:=(ExtendedCpuPageTable + $1fffff) shr 21;
|
|
GpuPagesSize:=GpuPages * $4000;
|
|
|
|
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_fmem_size - game_fmem_size) < size) then
|
|
begin
|
|
Writeln('[KERNEL] WARNING: Failed to allocate extended page table pool. shortage = '
|
|
,(game_fmem_size - bigapp_max_fmem_size) + $fffff + (size shr 20),
|
|
'MiB');
|
|
Exit(ENOMEM);
|
|
end;
|
|
|
|
param_3:=expand_budget_limit(size);
|
|
end;
|
|
|
|
//reserved physical pages
|
|
|
|
ExtendedSize:=size;
|
|
end;
|
|
|
|
end;
|
|
|
|
function dmem_process_relocated():Integer;
|
|
label
|
|
_no_mem_param,
|
|
_next;
|
|
var
|
|
proc_param:TSceProcParam;
|
|
|
|
mem_param:TSceKernelMemParam;
|
|
mem_param_size:QWORD;
|
|
|
|
size :QWORD;
|
|
m_256 :QWORD;
|
|
FMEM_SIZE:QWORD;
|
|
dmem_size:QWORD;
|
|
|
|
mmap_flags:Integer;
|
|
|
|
ExtendedCpuPageTable:QWORD;
|
|
ExtendedPageTable :QWORD;
|
|
ExtendedGpuPageTable:QWORD;
|
|
FlexibleMemorySize :QWORD;
|
|
|
|
ExtendedMemory1:Boolean;
|
|
ExtendedMemory2:Boolean;
|
|
begin
|
|
Result:=0;
|
|
|
|
if (p_proc.p_budget_ptype=PTYPE_BIG_APP) then
|
|
begin
|
|
mmap_flags:=g_appinfo.mmap_flags and 1;
|
|
end else
|
|
begin
|
|
mmap_flags:=0;
|
|
end;
|
|
|
|
proc_param:=Default(TSceProcParam);
|
|
Result:=copy_proc_param(@proc_param);
|
|
|
|
if (Result=ENOENT) then
|
|
begin
|
|
_no_mem_param:
|
|
mem_param:=Default(TSceKernelMemParam);
|
|
Result:=0;
|
|
end else
|
|
begin
|
|
if (Result=0) then
|
|
begin
|
|
if (proc_param._sceKernelMemParam=nil) then goto _no_mem_param;
|
|
|
|
mem_param_size:=fuword64(proc_param._sceKernelMemParam^.Size);
|
|
|
|
if (mem_param_size=QWORD($ffffffffffffffff)) then
|
|
begin
|
|
Result:=EACCES;
|
|
end else
|
|
begin
|
|
if (mem_param_size>sizeof(TSceKernelMemParam)) then
|
|
begin
|
|
mem_param_size:=sizeof(TSceKernelMemParam);
|
|
end;
|
|
|
|
mem_param:=Default(TSceKernelMemParam);
|
|
Result:=copyin(proc_param._sceKernelMemParam,@mem_param,mem_param_size);
|
|
|
|
if (Result=0) then goto _next;
|
|
end;
|
|
|
|
end;
|
|
//
|
|
Writeln('[KERNEL] ERROR: failed to load memory parameter: ',Result);
|
|
end;
|
|
|
|
_next:
|
|
|
|
if (Byte((mmap_flags xor 1) or ord(g_self_loading=0))=0) then
|
|
begin
|
|
g_self_loading:=0;
|
|
|
|
ExtendedMemory1:=true;
|
|
if (p_proc.p_sdk_version < $5000000) then
|
|
begin
|
|
if (mem_param.sceKernelExtendedMemory1=nil) then
|
|
begin
|
|
ExtendedMemory1:=False;
|
|
end else
|
|
begin
|
|
ExtendedMemory1:=fubyte(mem_param.sceKernelExtendedMemory1^)=1;
|
|
end;
|
|
end;
|
|
|
|
m_256:=QWORD(g_ext_game_fmem<>0) * $10000000;
|
|
|
|
//SCE_KERNEL_EXTENDED_DMEM_NEO_256
|
|
if (p_neomode<>0) and //only neomode
|
|
((not ExtendedMemory1) or (IGNORE_EXTENDED_DMEM_BASE<>0)) then
|
|
begin
|
|
//Subtract 256MB if the extended mode is disabled or ignored
|
|
|
|
BigAppMemory:=BigAppMemory - $10000000 {+ ((ret or $10)=$19) * (-0x10000000)};
|
|
|
|
dmem_size:=BigAppMemory - game_fmem_size;
|
|
|
|
//TODO: realloc dmem (DMEM_LIMIT->dmem_size)
|
|
|
|
size:=dmem_size;
|
|
if (FMEM_LIMIT <= dmem_size) then
|
|
begin
|
|
size:=FMEM_LIMIT;
|
|
end;
|
|
|
|
DMEM_LIMIT:=dmem_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 ,(game_fmem_size + m_256));
|
|
end;
|
|
|
|
ExtendedMemory2:=true;
|
|
if (p_proc.p_sdk_version < $5000000) then
|
|
begin
|
|
if (mem_param.sceKernelExtendedMemory2<>nil) then
|
|
begin
|
|
ExtendedMemory2:=False;
|
|
end else
|
|
begin
|
|
ExtendedMemory2:=fubyte(mem_param.sceKernelExtendedMemory2^)=1;
|
|
end;
|
|
end;
|
|
|
|
//SCE_KERNEL_EXTENDED_DMEM_BASE_128
|
|
if (p_neomode=0) and //only base mode
|
|
(IGNORE_EXTENDED_DMEM_BASE=0) then //extend mode not ignored
|
|
begin
|
|
|
|
if DUH_D1xxx then
|
|
begin
|
|
//
|
|
if (ExtendedMemory2) then
|
|
begin
|
|
Writeln('[System] : SCE_KERNEL_EXTENDED_DMEM_BASE_128 was ignored');
|
|
end;
|
|
//
|
|
end else
|
|
if (not ExtendedMemory2) then
|
|
begin
|
|
//Subtract 128MB if the extended mode is disabled
|
|
|
|
BigAppMemory:=BigAppMemory -$8000000 {+ ((ret and $ffffffe7)=1) * (-$8000000)};
|
|
|
|
dmem_size:=BigAppMemory - game_fmem_size;
|
|
|
|
//TODO: realloc dmem (DMEM_LIMIT->dmem_size)
|
|
|
|
size:=dmem_size;
|
|
if (FMEM_LIMIT <= dmem_size) then
|
|
begin
|
|
size:=FMEM_LIMIT;
|
|
end;
|
|
|
|
DMEM_LIMIT:=dmem_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 ,(game_fmem_size + m_256));
|
|
end;
|
|
|
|
end;
|
|
|
|
if (mem_param.sceKernelExtendedCpuPageTable=nil) then
|
|
begin
|
|
ExtendedCpuPageTable:=QWORD(Int64(-1));
|
|
end else
|
|
begin
|
|
ExtendedCpuPageTable:=fuword64(mem_param.sceKernelExtendedCpuPageTable^);
|
|
end;
|
|
|
|
if (mem_param.sceKernelExtendedPageTable=nil) then
|
|
begin
|
|
ExtendedPageTable:=QWORD(Int64(-1));
|
|
end else
|
|
begin
|
|
ExtendedPageTable:=fuword64(mem_param.sceKernelExtendedPageTable^);
|
|
end;
|
|
|
|
|
|
if (int64(ExtendedCpuPageTable) < 0) and
|
|
(int64(ExtendedPageTable) < 1) then
|
|
begin
|
|
ExtendedCpuPageTable:=0;
|
|
end else
|
|
if (ExtendedCpuPageTable > $1000000000) then
|
|
begin
|
|
ExtendedCpuPageTable:=0;
|
|
Writeln(stderr,'[KERNEL] ERROR: The extended CPU page table pool must be smaller than 64GiB');
|
|
Result:=ENOMEM;
|
|
end;
|
|
|
|
if (mem_param.sceKernelExtendedGpuPageTable=nil) then
|
|
begin
|
|
ExtendedGpuPageTable:=QWORD(Int64(-1));
|
|
end else
|
|
begin
|
|
ExtendedGpuPageTable:=fuword64(mem_param.sceKernelExtendedGpuPageTable^);
|
|
end;
|
|
|
|
ExtendedGpuPageTable:=(not SarInt64(ExtendedGpuPageTable,63)) and ExtendedGpuPageTable;
|
|
|
|
// MAX 64GB
|
|
if (ExtendedGpuPageTable < $1000000001) then
|
|
begin
|
|
ExtendedSize:=0;
|
|
FMEM_SIZE:=bigapp_max_fmem_size;
|
|
|
|
if (Result=0) then
|
|
begin
|
|
Result:=allocate_extended_page_table_pool(ExtendedCpuPageTable,ExtendedGpuPageTable,0);
|
|
|
|
FMEM_SIZE:=bigapp_max_fmem_size;
|
|
|
|
if (Result=0) then
|
|
begin
|
|
if (mem_param.sceKernelFlexibleMemorySize=nil) then
|
|
begin
|
|
Result:=0;
|
|
end else
|
|
begin
|
|
FlexibleMemorySize:=fuword64(mem_param.sceKernelFlexibleMemorySize^);
|
|
|
|
Result:=0;
|
|
FMEM_SIZE:=bigapp_max_fmem_size;
|
|
|
|
if (FlexibleMemorySize<>QWORD($ffffffffffffffff)) then
|
|
begin
|
|
FMEM_SIZE:=FMEM_BASE + FlexibleMemorySize;
|
|
|
|
if (bigapp_max_fmem_size < FMEM_SIZE) or
|
|
(FMEM_SIZE < bigapp_size) or
|
|
((FMEM_SIZE and QWORD(not PAGE_MASK))<>FMEM_SIZE) then
|
|
begin
|
|
Writeln(stderr,'[KERNEL] ERROR: invalid FMEM size (0x',HexStr(FlexibleMemorySize,16),') is specified.');
|
|
Result:=EINVAL;
|
|
FMEM_SIZE:=bigapp_max_fmem_size;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
end else
|
|
begin
|
|
Writeln('[KERNEL] ERROR: The extended GPU page table pool must be smaller than 64GiB');
|
|
Result:=ENOMEM;
|
|
ExtendedSize:=0;
|
|
FMEM_SIZE:=bigapp_max_fmem_size;
|
|
end;
|
|
|
|
if (FMEM_SIZE < game_fmem_size) then
|
|
begin
|
|
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
|
|
Result:=Integer($a0020326);
|
|
end;
|
|
end else
|
|
if (Result=0) then
|
|
begin
|
|
Result:=0;
|
|
set_bigapp_limits(FMEM_SIZE,0);
|
|
end;
|
|
|
|
end else
|
|
if (ExtendedSize=0) and
|
|
(mmap_flags<>0) then
|
|
begin
|
|
if (mem_param.sceKernelExtendedPageTable=nil) then
|
|
begin
|
|
ExtendedPageTable:=QWORD(Int64(-1));
|
|
end else
|
|
begin
|
|
ExtendedPageTable:=fuword64(mem_param.sceKernelExtendedPageTable^);
|
|
end;
|
|
|
|
if (Int64(ExtendedPageTable) < 1) or
|
|
(ExtendedPageTable=$100000000) then
|
|
begin
|
|
if (Int64(ExtendedPageTable) > 0) then
|
|
begin
|
|
allocate_extended_page_table_pool(ExtendedPageTable,0,0);
|
|
end;
|
|
end else
|
|
begin
|
|
Writeln(stderr,'[KERNEL] ERROR: failed to extend page table pool: ',Result);
|
|
end;
|
|
|
|
end;
|
|
|
|
Writeln('DMEM_LIMIT =0x',HexStr(DMEM_LIMIT,16));
|
|
Writeln('FMEM_LIMIT =0x',HexStr(FMEM_LIMIT,16));
|
|
Writeln('BigAppMem =0x',HexStr(BigAppMemory,16));
|
|
Writeln('game_fmem_size =0x',HexStr(game_fmem_size,16));
|
|
//
|
|
Writeln('vm_budget_dmem_alloc=0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_dmem_alloc),16));
|
|
Writeln('vm_budget_mlock =0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_mlock ),16));
|
|
Writeln('vm_budget_malloc =0x',HexStr(vm_budget_limit(PTYPE_BIG_APP,field_malloc ),16));
|
|
end;
|
|
|
|
function get_mlock_avail():QWORD;
|
|
var
|
|
used :QWORD;
|
|
limit:QWORD;
|
|
begin
|
|
Result:=0;
|
|
|
|
used :=vm_budget_used (p_proc.p_budget_ptype,field_mlock);
|
|
limit:=vm_budget_limit(p_proc.p_budget_ptype,field_mlock);
|
|
|
|
if (limit>used) then
|
|
begin
|
|
Result:=limit-used;
|
|
end;
|
|
end;
|
|
|
|
function get_mlock_total():QWORD;
|
|
begin
|
|
Result:=vm_budget_limit(p_proc.p_budget_ptype,field_mlock)
|
|
end;
|
|
|
|
function sys_budget_create(name:pchar;ptype:DWORD;new:Pointer;count:DWORD;prev:Pointer):Integer;
|
|
begin
|
|
//name != null
|
|
//ptype -> [0..3] (proc_type)
|
|
//new -> p_budget_resource
|
|
//count -> [0..11] (new/prev)
|
|
//prev -> p_budget_resource
|
|
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
|
|
end;
|
|
|
|
function sys_budget_delete(key:Integer):Integer;
|
|
begin
|
|
//key -> id_table
|
|
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
|
|
end;
|
|
|
|
function sys_budget_get(key:Integer;ptr:Pointer;psize:PInteger):Integer;
|
|
begin
|
|
//key -> [-2..-5] (budget limits [0..3]) else -> id_table
|
|
//ptr -> p_budget_resource
|
|
//psize -> in/out size
|
|
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
|
|
end;
|
|
|
|
function sys_budget_set(key:Integer):Integer;
|
|
begin
|
|
//key -> id_table
|
|
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
|
|
end;
|
|
|
|
function sys_budget_get_ptype(pid:Integer):Integer;
|
|
var
|
|
td:p_kthread;
|
|
begin
|
|
//sceKernelGetProcessType
|
|
|
|
td:=curkthread;
|
|
if (td=nil) then Exit(-1);
|
|
|
|
if (pid<>-1) and
|
|
(pid<>p_proc.p_pid) then
|
|
begin
|
|
Exit(ENOSYS);
|
|
end;
|
|
|
|
td^.td_retval[0]:=p_proc.p_budget_ptype;
|
|
|
|
Result:=0;
|
|
end;
|
|
|
|
function sys_budget_get_ptype_of_budget(key:Integer):Integer;
|
|
begin
|
|
//key -> id_table
|
|
Exit(ENOSYS); //sceSblACMgrIsSystemUcred
|
|
end;
|
|
|
|
function sys_budget_getid():Integer;
|
|
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 (g_ext_game_fmem<>0) then
|
|
begin
|
|
Writeln(stderr,'ext_game_fmem is already enabled');
|
|
Assert (false ,'ext_game_fmem is already enabled');
|
|
end;
|
|
|
|
g_ext_game_fmem:=1;
|
|
end;
|
|
as_disable_ext_game_fmem:
|
|
begin
|
|
g_ext_game_fmem:=0;
|
|
end;
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
//sceKernelNotifyAppStateChanged
|
|
function sys_app_state_change(state:Integer):Integer;
|
|
begin
|
|
//sceSblACMgrIsSyscoreProcess
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
procedure reset_2mb_mode;
|
|
var
|
|
size:QWORD;
|
|
begin
|
|
if (Int64(g_mode_2mb_size) < 1) then
|
|
begin
|
|
g_mode_2mb_size:=0;
|
|
g_mode_2mb_rsrv:=0;
|
|
end else
|
|
if (g_mode_2mb_size<>g_mode_2mb_rsrv) then
|
|
begin
|
|
Writeln(stderr,'2mpage budget');
|
|
Assert(false,'2mpage budget');
|
|
end else
|
|
begin
|
|
size:=g_mode_2mb_size;
|
|
|
|
g_mode_2mb_rsrv:=0;
|
|
g_mode_2mb_size:=0;
|
|
|
|
vm_budget_release(PTYPE_BIG_APP,field_mlock,size);
|
|
end;
|
|
|
|
g_mode_2mb:=M2MB_DISABLE;
|
|
end;
|
|
|
|
function kern_reserve_2mb_page(size:QWORD;mode:Integer):Integer;
|
|
var
|
|
save_game_fmem_size:QWORD;
|
|
size2:QWORD;
|
|
mode2:Integer;
|
|
begin
|
|
Result:=0;
|
|
|
|
save_game_fmem_size:=game_fmem_size;
|
|
|
|
if not ((g_mode_2mb=M2MB_DISABLE) and (g_mode_2mb_size=0)) then
|
|
begin
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
if (game_fmem_size<>bigapp_size) then
|
|
begin
|
|
Writeln(stderr,'[KERNEL] WARNING: The last bigapp termination handling was incomplete.');
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
mode2:=M2MB_DISABLE;
|
|
|
|
if (Int64(size) > PAGE_2MB_MASK) then
|
|
begin
|
|
mode2:=mode;
|
|
end;
|
|
|
|
if ((mode or 1)<>3) then
|
|
begin
|
|
mode2:=mode;
|
|
end;
|
|
|
|
if (mode2=M2MB_DEFAULT) then
|
|
begin
|
|
g_mode_2mb :=M2MB_DEFAULT;
|
|
g_mode_2mb_size:=0;
|
|
end else
|
|
if (mode2=M2MB_DISABLE) then
|
|
begin
|
|
g_mode_2mb :=M2MB_DISABLE;
|
|
g_mode_2mb_size:=-1;
|
|
end else
|
|
begin
|
|
|
|
if (Int64(size) > $1bffffff) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
if ((mode2 or 1)<>3) then
|
|
begin
|
|
Exit(EINVAL);
|
|
end;
|
|
|
|
if (Int64(size) > -1) then
|
|
begin
|
|
size2:=size;
|
|
end else
|
|
begin
|
|
size2:=size + PAGE_2MB_MASK;
|
|
end;
|
|
|
|
size2:=size2 and QWORD(not PAGE_2MB_MASK);
|
|
|
|
if (bigapp_max_fmem_size < (game_fmem_size + size2)) then
|
|
begin
|
|
size:=bigapp_max_fmem_size;
|
|
end else
|
|
begin
|
|
size:=game_fmem_size + size2;
|
|
end;
|
|
|
|
set_bigapp_limits(size,0);
|
|
|
|
if (vm_budget_reserve(PTYPE_BIG_APP,field_mlock,size2)<>0) then
|
|
begin
|
|
set_bigapp_limits(save_game_fmem_size,0);
|
|
Exit(ENOMEM);
|
|
end;
|
|
|
|
g_mode_2mb :=mode2;
|
|
g_mode_2mb_size:=size2;
|
|
g_mode_2mb_rsrv:=size2;
|
|
end;
|
|
|
|
end;
|
|
|
|
function sys_reserve_2mb_page(size:QWORD;mode:Integer):Integer;
|
|
begin
|
|
//sceSblACMgrIsSyscoreProcess
|
|
Exit(EPERM);
|
|
end;
|
|
|
|
end.
|
|
|
|
|
|
|
|
|